premiere-pro-mcp 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +121 -8
- package/artifacts/MCPBridgeCEP.zxp +0 -0
- package/cep-plugin/CSXS/manifest.xml +3 -3
- package/cep-plugin/index.html +18 -6
- package/cep-plugin/main.js +125 -1
- package/cep-plugin/styles.css +37 -1
- package/cep-plugin/updater.cjs +74 -0
- package/dist/advanced-feature-support.d.ts +140 -0
- package/dist/advanced-feature-support.js +157 -0
- package/dist/bridge/uxp-websocket-bridge.d.ts +61 -0
- package/dist/bridge/uxp-websocket-bridge.js +249 -0
- package/dist/index.js +24 -2
- package/dist/platform-capabilities.d.ts +32 -1
- package/dist/platform-capabilities.js +47 -2
- package/dist/security/capabilities.js +2 -2
- package/dist/server.d.ts +5 -1
- package/dist/server.js +13 -6
- package/dist/tool-capability-report.d.ts +55 -0
- package/dist/tool-capability-report.js +148 -0
- package/dist/tools/av-settings.d.ts +119 -0
- package/dist/tools/av-settings.js +210 -0
- package/dist/tools/export.d.ts +100 -0
- package/dist/tools/export.js +160 -2
- package/dist/tools/health.d.ts +206 -1
- package/dist/tools/health.js +49 -2
- package/dist/tools/recovery.d.ts +45 -0
- package/dist/tools/recovery.js +189 -0
- package/dist/tools/uxp.d.ts +71 -0
- package/dist/tools/uxp.js +53 -0
- package/package.json +5 -2
- package/scripts/build-claude-desktop.mjs +71 -0
- package/uxp-plugin/README.md +43 -2
- package/uxp-plugin/commands.cjs +163 -0
- package/uxp-plugin/index.cjs +327 -25
- package/uxp-plugin/index.html +7 -6
- package/uxp-plugin/manifest.json +1 -1
- package/uxp-plugin/protocol.cjs +82 -3
- package/uxp-plugin/transcript.cjs +95 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.4.0] - 2026-07-26
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added in-panel connector update discovery and trusted downloads from GitHub Releases.
|
|
14
|
+
- Added authenticated MCP-to-UXP WebSocket transport, transcript and caption inspection, event-driven
|
|
15
|
+
state reporting, operation semantics, and supported video-transition workflows.
|
|
16
|
+
- Added recovery diagnostics, export verification, AV inspection, capability reporting, and
|
|
17
|
+
collaboration/AI feature eligibility discovery.
|
|
18
|
+
- Added installable Codex, Claude Code, and Claude Desktop distributions.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Expanded the MCP surface to 278 tools and aligned documentation, plugin metadata, and distribution
|
|
23
|
+
manifests with the new release.
|
|
24
|
+
- Added automated signed CEP connector assets and Claude Desktop bundles to GitHub releases.
|
|
25
|
+
|
|
9
26
|
## [1.3.1] - 2026-07-25
|
|
10
27
|
|
|
11
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Give AI full control over Adobe Premiere Pro.**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
278 tools across 31 modules, 3 resources, and 4 guided workflows.
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
[](https://nodejs.org)
|
|
@@ -25,7 +25,7 @@ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that l
|
|
|
25
25
|
"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."
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
The AI handles the entire workflow through
|
|
28
|
+
The AI handles the entire workflow through 278 tools spanning the supported ExtendScript, QE DOM, and safe edit-planning surfaces.
|
|
29
29
|
|
|
30
30
|
### What's new in 1.3.1
|
|
31
31
|
|
|
@@ -43,7 +43,7 @@ The AI handles the entire workflow through 269 tools spanning the supported Exte
|
|
|
43
43
|
- **Safe edit plans:** preview compound insert/remove operations, bind approval to a SHA-256 plan token, then apply the validated plan in one bridge command.
|
|
44
44
|
- **Capability profiles:** unsafe scripting is disabled by default and requires explicit `unsafe-script` authority.
|
|
45
45
|
- **Modern MCP responses:** tools expose safety annotations and structured results; four workflow prompts and a machine-readable workflow resource guide common edits.
|
|
46
|
-
- **UXP bridge preview:** a packaged Premiere 25.6+ panel adds capability discovery, state events, reconnecting WebSocket transport, and supported frame export with file verification. Live host verification is still required.
|
|
46
|
+
- **UXP bridge preview:** a packaged Premiere 25.6+ panel adds capability discovery, event-driven state notifications with a deduplicated polling fallback, correlated operation lifecycle events, reconnecting WebSocket transport, and supported frame export with file verification. Cancellation is cooperative before non-cancellable host calls; no atomic rollback is claimed. Live host verification is still required.
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
@@ -217,6 +217,58 @@ Add to your VS Code MCP server configuration:
|
|
|
217
217
|
|
|
218
218
|
The default bridge directory is derived from the operating system on both sides, so most local setups should not set `PREMIERE_TEMP_DIR`. If you override it, use the same absolute path in the MCP server and CEP panel; Windows and macOS paths are not interchangeable.
|
|
219
219
|
|
|
220
|
+
### Codex plugin
|
|
221
|
+
|
|
222
|
+
This repository includes an installable Codex plugin that bundles the local MCP
|
|
223
|
+
server with a safety-oriented Premiere editing skill.
|
|
224
|
+
|
|
225
|
+
From a clone of this repository:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
codex plugin marketplace add .
|
|
229
|
+
codex plugin add premiere-pro@premiere-pro-mcp
|
|
230
|
+
npx -y premiere-pro-mcp@1.3.1 --install-cep
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Restart Premiere Pro and start a new Codex session after installation. The plugin
|
|
234
|
+
launches `premiere-pro-mcp@1.3.1` through `npx`; the separate CEP installation is
|
|
235
|
+
required because the MCP server communicates with the running Premiere host through
|
|
236
|
+
the local bridge.
|
|
237
|
+
|
|
238
|
+
The plugin source lives in [`plugins/premiere-pro`](plugins/premiere-pro), and the
|
|
239
|
+
repository marketplace manifest lives in
|
|
240
|
+
[`.agents/plugins/marketplace.json`](.agents/plugins/marketplace.json).
|
|
241
|
+
|
|
242
|
+
### Claude
|
|
243
|
+
|
|
244
|
+
For Claude Code, add this repository as a marketplace and install the plugin:
|
|
245
|
+
|
|
246
|
+
```text
|
|
247
|
+
/plugin marketplace add leancoderkavy/premiere-pro-mcp
|
|
248
|
+
/plugin install premiere-pro@premiere-pro-mcp
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Then install the Premiere bridge and start a new Claude Code session:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
npx -y premiere-pro-mcp@1.3.1 --install-cep
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The Claude Code package lives in
|
|
258
|
+
[`claude-plugins/premiere-pro`](claude-plugins/premiere-pro), with its marketplace
|
|
259
|
+
at [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json).
|
|
260
|
+
|
|
261
|
+
Claude Desktop uses the self-contained MCP Bundle format, formerly called Desktop
|
|
262
|
+
Extensions. Build both the current `.mcpb` artifact and a legacy `.dxt` copy with:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
npm run build:claude
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Install the resulting file from `artifacts/` through **Settings > Extensions >
|
|
269
|
+
Advanced settings > Install Extension**. The Premiere CEP bridge must still be
|
|
270
|
+
installed separately.
|
|
271
|
+
|
|
220
272
|
### Windows and macOS capability coverage
|
|
221
273
|
|
|
222
274
|
| Surface | Windows | macOS | Verification boundary |
|
|
@@ -226,7 +278,58 @@ The default bridge directory is derived from the operating system on both sides,
|
|
|
226
278
|
| npm CEP installer | Copies plugin and verifies `REG_SZ` debug keys | Copies plugin and verifies the installed manifest/debug settings | Restart Premiere after installation |
|
|
227
279
|
| CI build and unit tests | Node 18 and 22 | Node 18 and 22 | GitHub-hosted OS runners; no Adobe host is available in CI |
|
|
228
280
|
|
|
229
|
-
`get_capabilities` reports the current operating system, temp directory, CEP/UXP coverage, enabled authority profile, and any live-host verification still required. It
|
|
281
|
+
`get_capabilities` reports the current operating system, temp directory, CEP/UXP coverage, enabled authority profile, and any live-host verification still required. It also includes a `tools` catalog generated from the tools actually registered by the server. Every entry identifies:
|
|
282
|
+
|
|
283
|
+
- the execution backend (`local`, CEP/ExtendScript, QE, or orchestrator);
|
|
284
|
+
- static support status (`supported`, `limited`, `experimental`, or `unsupported`);
|
|
285
|
+
- the minimum Premiere version known to the server;
|
|
286
|
+
- the required authority and whether the current profile enables it;
|
|
287
|
+
- the verification boundary and whether a live Premiere host is required; and
|
|
288
|
+
- relevant operational notes.
|
|
289
|
+
|
|
290
|
+
QE-backed tools are reported as `experimental` because QE is undocumented and can vary between Premiere builds. Authority availability is reported separately from implementation support, so disabling `edit`, for example, does not incorrectly label editing tools as unsupported. Static metadata never claims that a Premiere operation succeeded; use `ping` and inspect each tool result for runtime evidence.
|
|
291
|
+
|
|
292
|
+
Tools with mixed execution boundaries can provide explicit operational metadata at registration. This is used for local file verification, static feature-support reports, and hybrid local-plus-Premiere validation so the capability catalog does not infer a host dependency from naming alone.
|
|
293
|
+
|
|
294
|
+
### Collaboration and AI feature boundaries
|
|
295
|
+
|
|
296
|
+
`get_advanced_feature_support` returns a machine-readable matrix for Productions,
|
|
297
|
+
Team Projects, Frame.io, Media Intelligence, Generative Extend, Object Mask,
|
|
298
|
+
caption translation, Speech-to-Text, Enhance Speech, and Remix. Pass an optional
|
|
299
|
+
Premiere version, intended backend, confirmed entitlements, and network state to
|
|
300
|
+
evaluate prerequisites without conflating them with API availability. It
|
|
301
|
+
distinguishes documented APIs from entitlements, network prerequisites, separate
|
|
302
|
+
service APIs, and user-assisted operations without using menu automation or
|
|
303
|
+
private APIs.
|
|
304
|
+
|
|
305
|
+
The report tool itself is local: it does not contact Premiere and is callable
|
|
306
|
+
through the current MCP server. Each feature entry separately reports whether
|
|
307
|
+
its operations are callable through the production CEP transport. Productions
|
|
308
|
+
reports only static backend/version eligibility until a UXP host performs live
|
|
309
|
+
capability negotiation.
|
|
310
|
+
|
|
311
|
+
- Productions exposes documented read-only state through UXP, but the production
|
|
312
|
+
MCP transport is still CEP.
|
|
313
|
+
- Frame.io needs a separately authenticated Frame.io API integration; an account
|
|
314
|
+
entitlement alone does not make it callable through Premiere's DOM.
|
|
315
|
+
- Transcript JSON import/export is documented in UXP. Starting Speech-to-Text is not.
|
|
316
|
+
- The remaining AI operations are user-assisted or unsupported by documented
|
|
317
|
+
public APIs. The tool explains what can be inspected after a user completes
|
|
318
|
+
the operation and where artifact provenance cannot be established safely.
|
|
319
|
+
- The server never uses menu automation, private APIs, clip-name heuristics, or
|
|
320
|
+
duration changes as proof that an AI operation occurred.
|
|
321
|
+
|
|
322
|
+
### Authenticated UXP connection
|
|
323
|
+
|
|
324
|
+
The MCP server can accept a local UXP panel connection and invoke the UXP commands that are currently implemented:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
PREMIERE_UXP_TOKEN="replace-with-a-long-random-secret" premiere-pro-mcp
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Enter the same token in the UXP panel. The listener binds only to `127.0.0.1:7777`, authenticates the WebSocket upgrade, requires a versioned capability handshake, correlates concurrent requests, and fails pending work on timeout or disconnect. Set `PREMIERE_UXP_PORT` to use another loopback port.
|
|
331
|
+
|
|
332
|
+
When enabled, MCP discovery includes `get_uxp_capabilities`, `get_uxp_state`, and `export_frame_uxp`. A failed UXP command is never silently retried through CEP because the first operation may have partially succeeded.
|
|
230
333
|
|
|
231
334
|
---
|
|
232
335
|
|
|
@@ -270,7 +373,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
270
373
|
|
|
271
374
|
---
|
|
272
375
|
|
|
273
|
-
## Tools (
|
|
376
|
+
## Tools (278)
|
|
274
377
|
|
|
275
378
|
### Discovery & Inspection (10 + 10)
|
|
276
379
|
|
|
@@ -286,6 +389,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
286
389
|
| `search_project_items` | Filter by name, extension, offline status, color label |
|
|
287
390
|
| `get_premiere_state` | Full snapshot: project, sequence, playhead, selection |
|
|
288
391
|
| `inspect_dom_object` | Explore any Premiere Pro DOM object interactively |
|
|
392
|
+
| `get_advanced_feature_support` | Collaboration/AI API support, prerequisites, entitlements, and user-assisted boundaries |
|
|
289
393
|
|
|
290
394
|
### Project Management (26)
|
|
291
395
|
|
|
@@ -341,16 +445,23 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
341
445
|
| `get_value_at_time` | Query interpolated value at any time |
|
|
342
446
|
| `set_color_value` | Set color properties on effects |
|
|
343
447
|
|
|
344
|
-
### Export & Encoding (
|
|
448
|
+
### Export & Encoding (16)
|
|
345
449
|
|
|
346
450
|
| Tool | Description |
|
|
347
451
|
| :--- | :---------- |
|
|
348
452
|
| `export_sequence` | Export via Adobe Media Encoder |
|
|
453
|
+
| `validate_export_preset` | Validate an `.epr` file and resolve its output extension in Premiere |
|
|
454
|
+
| `verify_delivery_file` | Verify output size and calculate SHA-256/SHA-512 checksums |
|
|
349
455
|
| `capture_frame` | Export frame as PNG, return as base64 image |
|
|
350
456
|
| `export_as_fcp_xml` / `export_aaf` / `export_omf` | Interchange formats |
|
|
351
457
|
| `encode_project_item` / `encode_file` | Direct encoding |
|
|
352
458
|
| `start_batch_encode` | Start render queue |
|
|
353
459
|
|
|
460
|
+
Premiere's documented automation surfaces do not currently expose OTIO or EDL
|
|
461
|
+
interchange, Render and Replace, cloud publishing, or Content Credentials export
|
|
462
|
+
configuration. `get_capabilities` reports these delivery gaps explicitly rather
|
|
463
|
+
than presenting UI-only operations as available tools.
|
|
464
|
+
|
|
354
465
|
### Source Monitor & Playback (7 + 4)
|
|
355
466
|
|
|
356
467
|
| Tool | Description |
|
|
@@ -495,12 +606,13 @@ premiere-pro-mcp/
|
|
|
495
606
|
├── src/
|
|
496
607
|
│ ├── index.ts # Entry point — stdio transport setup
|
|
497
608
|
│ ├── http-server.ts # Entry point — HTTP/SSE transport (Fly.io / remote)
|
|
498
|
-
│ ├── server.ts # MCP server — registers
|
|
609
|
+
│ ├── server.ts # MCP server — registers 278 tools + 3 resources + 4 prompts
|
|
499
610
|
│ ├── bridge/
|
|
500
611
|
│ │ ├── file-bridge.ts # File-based IPC (write .jsx, poll .json)
|
|
501
612
|
│ │ └── script-builder.ts # ExtendScript generator with ES3 helpers
|
|
502
|
-
│ ├── tools/ #
|
|
613
|
+
│ ├── tools/ # 31 tool modules
|
|
503
614
|
│ │ ├── discovery.ts # Project discovery and queries
|
|
615
|
+
│ │ ├── recovery.ts # Read-only autosave discovery and private bridge telemetry
|
|
504
616
|
│ │ ├── project.ts # Project management and import
|
|
505
617
|
│ │ ├── media.ts # Media and proxy management
|
|
506
618
|
│ │ ├── sequence.ts # Sequence creation and settings
|
|
@@ -508,6 +620,7 @@ premiere-pro-mcp/
|
|
|
508
620
|
│ │ ├── effects.ts # Effect application and color correction
|
|
509
621
|
│ │ ├── transitions.ts # Transition management (QE DOM)
|
|
510
622
|
│ │ ├── audio.ts # Audio levels and keyframes
|
|
623
|
+
│ │ ├── av-settings.ts # Documented AV inspection, mapping, and capability boundaries
|
|
511
624
|
│ │ ├── text.ts # Text overlays and MOGRTs
|
|
512
625
|
│ │ ├── markers.ts # Sequence and clip markers
|
|
513
626
|
│ │ ├── tracks.ts # Track add/delete/lock/visibility
|
|
Binary file
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.4.0" ExtensionBundleName="MCP Bridge">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.
|
|
5
|
-
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.
|
|
4
|
+
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.4.0"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.4.0"/>
|
|
6
6
|
</ExtensionList>
|
|
7
7
|
<ExecutionEnvironment>
|
|
8
8
|
<HostList>
|
package/cep-plugin/index.html
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="auto-start"><span></span>Auto-start</div>
|
|
18
18
|
</header>
|
|
19
19
|
|
|
20
|
-
<section class="status-panel" aria-live="polite">
|
|
20
|
+
<section class="status-panel" role="status" aria-live="polite" aria-atomic="true">
|
|
21
21
|
<div class="status-indicator" aria-hidden="true">
|
|
22
22
|
<div class="status-ring"><div class="status-dot connected" id="statusDot"></div></div>
|
|
23
23
|
</div>
|
|
@@ -46,22 +46,33 @@
|
|
|
46
46
|
<label class="sr-only" for="tempDir">Temporary bridge directory</label>
|
|
47
47
|
<div class="path-field">
|
|
48
48
|
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M2.5 5.5h5l1.5 2h8.5v8h-15v-10Z"/></svg>
|
|
49
|
-
<input type="text" id="tempDir" value="" spellcheck="false">
|
|
49
|
+
<input type="text" id="tempDir" value="" spellcheck="false" autocomplete="off" aria-describedby="tempDirHelp">
|
|
50
50
|
</div>
|
|
51
|
-
<p class="field-help">Commands and responses are exchanged through this local folder.</p>
|
|
51
|
+
<p class="field-help" id="tempDirHelp">Commands and responses are exchanged through this local folder.</p>
|
|
52
52
|
</section>
|
|
53
53
|
|
|
54
54
|
<div class="action-row">
|
|
55
|
-
<button id="btnStart" class="button button-primary" onclick="startBridge()" type="button">
|
|
55
|
+
<button id="btnStart" class="button button-primary" onclick="startBridge()" type="button" aria-controls="log">
|
|
56
56
|
<svg viewBox="0 0 20 20" aria-hidden="true"><path class="fill-icon" d="m7 5 8 5-8 5V5Z"/></svg>
|
|
57
57
|
Start Bridge
|
|
58
58
|
</button>
|
|
59
|
-
<button id="btnStop" class="button button-stop" onclick="stopBridge()" type="button" disabled>
|
|
59
|
+
<button id="btnStop" class="button button-stop" onclick="stopBridge()" type="button" aria-controls="log" disabled>
|
|
60
60
|
<svg viewBox="0 0 20 20" aria-hidden="true"><rect class="fill-icon" x="6" y="6" width="8" height="8" rx="1"/></svg>
|
|
61
61
|
Stop
|
|
62
62
|
</button>
|
|
63
63
|
</div>
|
|
64
64
|
|
|
65
|
+
<section class="update-section" aria-live="polite">
|
|
66
|
+
<div class="update-copy">
|
|
67
|
+
<span class="section-label">Connector updates</span>
|
|
68
|
+
<strong id="updateTitle">Version 1.4.0</strong>
|
|
69
|
+
<span id="updateDetail">Checking for updates…</span>
|
|
70
|
+
</div>
|
|
71
|
+
<button id="btnUpdate" class="button button-update" onclick="handleUpdateClick()" type="button" disabled>
|
|
72
|
+
Check again
|
|
73
|
+
</button>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
65
76
|
<section class="activity-section">
|
|
66
77
|
<div class="section-heading activity-heading">
|
|
67
78
|
<div>
|
|
@@ -70,11 +81,12 @@
|
|
|
70
81
|
</div>
|
|
71
82
|
<span class="activity-state"><span></span>Listening</span>
|
|
72
83
|
</div>
|
|
73
|
-
<div id="log" role="log" aria-live="polite"></div>
|
|
84
|
+
<div id="log" role="log" aria-live="polite" aria-relevant="additions" tabindex="0" aria-label="Bridge activity log"></div>
|
|
74
85
|
</section>
|
|
75
86
|
</main>
|
|
76
87
|
|
|
77
88
|
<script src="CSInterface.js"></script>
|
|
89
|
+
<script src="updater.cjs"></script>
|
|
78
90
|
<script src="main.js"></script>
|
|
79
91
|
</body>
|
|
80
92
|
</html>
|
package/cep-plugin/main.js
CHANGED
|
@@ -26,7 +26,9 @@ function log(msg, cls) {
|
|
|
26
26
|
function setStatus(state, text) {
|
|
27
27
|
var dot = document.getElementById("statusDot");
|
|
28
28
|
dot.className = "status-dot " + state;
|
|
29
|
-
document.getElementById("statusText")
|
|
29
|
+
var statusText = document.getElementById("statusText");
|
|
30
|
+
statusText.textContent = text;
|
|
31
|
+
statusText.setAttribute("data-state", state || "stopped");
|
|
30
32
|
var detail = document.getElementById("statusDetail");
|
|
31
33
|
if (detail) {
|
|
32
34
|
if (state === "connected") detail.textContent = "Premiere Pro link is active";
|
|
@@ -55,7 +57,9 @@ function nodeRequire(moduleName) {
|
|
|
55
57
|
var fs = nodeRequire("fs");
|
|
56
58
|
var path = nodeRequire("path");
|
|
57
59
|
var os = nodeRequire("os");
|
|
60
|
+
var https = nodeRequire("https");
|
|
58
61
|
tempDir = path.join(os.tmpdir(), "premiere-mcp-bridge");
|
|
62
|
+
var latestUpdate = null;
|
|
59
63
|
|
|
60
64
|
function ensureDir(dir) {
|
|
61
65
|
try {
|
|
@@ -204,6 +208,7 @@ function startBridge() {
|
|
|
204
208
|
tempDir = document.getElementById("tempDir").value.trim();
|
|
205
209
|
if (!tempDir) {
|
|
206
210
|
log("Please set a temp directory", "err");
|
|
211
|
+
document.getElementById("tempDir").focus();
|
|
207
212
|
return;
|
|
208
213
|
}
|
|
209
214
|
|
|
@@ -250,6 +255,124 @@ function saveTempDir() {
|
|
|
250
255
|
} catch (e) {}
|
|
251
256
|
}
|
|
252
257
|
|
|
258
|
+
// ---- Connector Updates ----
|
|
259
|
+
function setUpdateUI(title, detail, buttonText, disabled) {
|
|
260
|
+
document.getElementById("updateTitle").textContent = title;
|
|
261
|
+
document.getElementById("updateDetail").textContent = detail;
|
|
262
|
+
var button = document.getElementById("btnUpdate");
|
|
263
|
+
button.textContent = buttonText;
|
|
264
|
+
button.disabled = !!disabled;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function checkForUpdates() {
|
|
268
|
+
latestUpdate = null;
|
|
269
|
+
setUpdateUI(
|
|
270
|
+
"Version " + MCPBridgeUpdater.CURRENT_VERSION,
|
|
271
|
+
"Checking for updates…",
|
|
272
|
+
"Checking…",
|
|
273
|
+
true
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
var request = https.get(
|
|
277
|
+
MCPBridgeUpdater.LATEST_RELEASE_API,
|
|
278
|
+
{
|
|
279
|
+
headers: {
|
|
280
|
+
Accept: "application/vnd.github+json",
|
|
281
|
+
"User-Agent": "premiere-pro-mcp-connector/" + MCPBridgeUpdater.CURRENT_VERSION,
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
function (response) {
|
|
285
|
+
var body = "";
|
|
286
|
+
response.setEncoding("utf8");
|
|
287
|
+
response.on("data", function (chunk) {
|
|
288
|
+
if (body.length < 1024 * 1024) body += chunk;
|
|
289
|
+
});
|
|
290
|
+
response.on("end", function () {
|
|
291
|
+
if (response.statusCode !== 200) {
|
|
292
|
+
showUpdateCheckError("Could not check GitHub (HTTP " + response.statusCode + ").");
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
var release = JSON.parse(body);
|
|
297
|
+
var latestVersion = MCPBridgeUpdater.normalizeVersion(
|
|
298
|
+
release.tag_name || release.name
|
|
299
|
+
);
|
|
300
|
+
if (!latestVersion) throw new Error("Release has no version");
|
|
301
|
+
|
|
302
|
+
if (
|
|
303
|
+
MCPBridgeUpdater.compareVersions(
|
|
304
|
+
latestVersion,
|
|
305
|
+
MCPBridgeUpdater.CURRENT_VERSION
|
|
306
|
+
) > 0
|
|
307
|
+
) {
|
|
308
|
+
latestUpdate = {
|
|
309
|
+
version: latestVersion,
|
|
310
|
+
url: MCPBridgeUpdater.chooseDownloadUrl(release),
|
|
311
|
+
};
|
|
312
|
+
setUpdateUI(
|
|
313
|
+
"Version " + latestVersion + " is available",
|
|
314
|
+
"Download it, then close Premiere and run the installer.",
|
|
315
|
+
"Download update",
|
|
316
|
+
false
|
|
317
|
+
);
|
|
318
|
+
} else {
|
|
319
|
+
setUpdateUI(
|
|
320
|
+
"Version " + MCPBridgeUpdater.CURRENT_VERSION,
|
|
321
|
+
"You have the latest connector.",
|
|
322
|
+
"Check again",
|
|
323
|
+
false
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
} catch (e) {
|
|
327
|
+
showUpdateCheckError("GitHub returned an unreadable release.");
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
request.setTimeout(10000, function () {
|
|
333
|
+
request.destroy(new Error("Update check timed out"));
|
|
334
|
+
});
|
|
335
|
+
request.on("error", function () {
|
|
336
|
+
showUpdateCheckError("Unable to check while offline.");
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function showUpdateCheckError(message) {
|
|
341
|
+
setUpdateUI(
|
|
342
|
+
"Version " + MCPBridgeUpdater.CURRENT_VERSION,
|
|
343
|
+
message,
|
|
344
|
+
"Check again",
|
|
345
|
+
false
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function handleUpdateClick() {
|
|
350
|
+
if (!latestUpdate) {
|
|
351
|
+
checkForUpdates();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (!MCPBridgeUpdater.isTrustedDownloadUrl(latestUpdate.url)) {
|
|
355
|
+
showUpdateCheckError("The update link was not trusted.");
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
var childProcess = nodeRequire("child_process");
|
|
360
|
+
var command =
|
|
361
|
+
os.platform() === "win32"
|
|
362
|
+
? ["cmd.exe", ["/d", "/s", "/c", "start", "", latestUpdate.url]]
|
|
363
|
+
: ["open", [latestUpdate.url]];
|
|
364
|
+
var child = childProcess.spawn(command[0], command[1], {
|
|
365
|
+
detached: true,
|
|
366
|
+
stdio: "ignore",
|
|
367
|
+
});
|
|
368
|
+
child.unref();
|
|
369
|
+
document.getElementById("updateDetail").textContent =
|
|
370
|
+
"Download opened. Close Premiere before installing.";
|
|
371
|
+
} catch (e) {
|
|
372
|
+
showUpdateCheckError("Could not open the download. Try again.");
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
253
376
|
// ---- Init ----
|
|
254
377
|
(function init() {
|
|
255
378
|
// Set the default temp dir in the input field
|
|
@@ -273,4 +396,5 @@ function saveTempDir() {
|
|
|
273
396
|
ensureDir(tempDir);
|
|
274
397
|
log("Auto-starting bridge...");
|
|
275
398
|
setTimeout(startBridge, 500);
|
|
399
|
+
setTimeout(checkForUpdates, 1200);
|
|
276
400
|
})();
|
package/cep-plugin/styles.css
CHANGED
|
@@ -117,6 +117,10 @@ button { -webkit-appearance: none; }
|
|
|
117
117
|
.section-label { display: block; margin-bottom: 4px; color: var(--text-muted); font-size: 9px; font-weight: 650; letter-spacing: .09em; text-transform: uppercase; }
|
|
118
118
|
.status-copy { min-width: 0; }
|
|
119
119
|
.status-copy strong { display: block; overflow: hidden; color: var(--text); font-size: 14px; font-weight: 650; line-height: 1.3; text-overflow: ellipsis; white-space: nowrap; }
|
|
120
|
+
.status-copy strong::before { content: "■ "; color: var(--text-muted); }
|
|
121
|
+
.status-copy strong[data-state="connected"]::before { content: "✓ "; color: var(--green); }
|
|
122
|
+
.status-copy strong[data-state="waiting"]::before { content: "… "; color: var(--amber); }
|
|
123
|
+
.status-copy strong[data-state="error"]::before { content: "! "; color: var(--red); }
|
|
120
124
|
.status-copy #statusDetail { display: block; overflow: hidden; margin-top: 3px; color: var(--text-secondary); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
|
|
121
125
|
|
|
122
126
|
.command-stat { padding-left: 14px; text-align: right; }
|
|
@@ -183,6 +187,32 @@ button { -webkit-appearance: none; }
|
|
|
183
187
|
.button-stop:hover { border-color: var(--red); background: rgba(255, 101, 101, .08); }
|
|
184
188
|
.button:disabled { border-color: var(--border); background: var(--surface); color: #5f5e65; cursor: default; }
|
|
185
189
|
|
|
190
|
+
.update-section {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
gap: 12px;
|
|
194
|
+
margin-bottom: 14px;
|
|
195
|
+
padding: 11px 12px;
|
|
196
|
+
border: 1px solid var(--border);
|
|
197
|
+
border-radius: var(--radius);
|
|
198
|
+
background: var(--surface);
|
|
199
|
+
}
|
|
200
|
+
.update-copy { min-width: 0; flex: 1; }
|
|
201
|
+
.update-copy strong, .update-copy > span:last-child { display: block; }
|
|
202
|
+
.update-copy strong { font-size: 11px; font-weight: 600; }
|
|
203
|
+
.update-copy > span:last-child { margin-top: 3px; color: var(--text-muted); font-size: 9px; line-height: 1.4; }
|
|
204
|
+
.button-update {
|
|
205
|
+
width: auto;
|
|
206
|
+
min-width: 92px;
|
|
207
|
+
height: 30px;
|
|
208
|
+
padding: 0 10px;
|
|
209
|
+
border-color: var(--border-strong);
|
|
210
|
+
background: var(--surface-raised);
|
|
211
|
+
color: var(--violet-hover);
|
|
212
|
+
white-space: nowrap;
|
|
213
|
+
}
|
|
214
|
+
.button-update:hover { border-color: var(--violet); background: var(--violet-soft); }
|
|
215
|
+
|
|
186
216
|
.activity-section { display: flex; flex: 1; min-height: 120px; flex-direction: column; }
|
|
187
217
|
.activity-heading { align-items: center; margin: 2px 0 8px; }
|
|
188
218
|
.activity-state { display: flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: 9px; }
|
|
@@ -211,7 +241,7 @@ button { -webkit-appearance: none; }
|
|
|
211
241
|
|
|
212
242
|
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
213
243
|
|
|
214
|
-
button:focus-visible { outline:
|
|
244
|
+
button:focus-visible, input:focus-visible, #log:focus-visible { outline: 2px solid var(--violet-hover); outline-offset: 2px; }
|
|
215
245
|
|
|
216
246
|
@media (max-width: 330px) {
|
|
217
247
|
.panel-shell { padding-right: 10px; padding-left: 10px; }
|
|
@@ -225,3 +255,9 @@ button:focus-visible { outline: 1px solid var(--violet); outline-offset: 2px; }
|
|
|
225
255
|
@media (prefers-reduced-motion: reduce) {
|
|
226
256
|
*, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
|
|
227
257
|
}
|
|
258
|
+
|
|
259
|
+
@media (forced-colors: active) {
|
|
260
|
+
.status-dot, .auto-start > span, .activity-state > span { forced-color-adjust: none; border: 1px solid CanvasText; }
|
|
261
|
+
.button, .path-field input, #log, .status-panel { border-color: CanvasText; }
|
|
262
|
+
.status-copy strong::before { color: CanvasText !important; }
|
|
263
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* MCP Bridge update helpers. Kept dependency-free for the older Chromium
|
|
2
|
+
* runtime embedded in CEP. */
|
|
3
|
+
(function (root, factory) {
|
|
4
|
+
var api = factory();
|
|
5
|
+
if (typeof module === "object" && module.exports) module.exports = api;
|
|
6
|
+
root.MCPBridgeUpdater = api;
|
|
7
|
+
})(this, function () {
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
var CURRENT_VERSION = "1.4.0";
|
|
11
|
+
var LATEST_RELEASE_API =
|
|
12
|
+
"https://api.github.com/repos/leancoderkavy/premiere-pro-mcp/releases/latest";
|
|
13
|
+
var RELEASES_URL =
|
|
14
|
+
"https://github.com/leancoderkavy/premiere-pro-mcp/releases/latest";
|
|
15
|
+
|
|
16
|
+
function normalizeVersion(value) {
|
|
17
|
+
return String(value || "")
|
|
18
|
+
.trim()
|
|
19
|
+
.replace(/^v/i, "")
|
|
20
|
+
.split("-")[0];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function compareVersions(left, right) {
|
|
24
|
+
var a = normalizeVersion(left).split(".");
|
|
25
|
+
var b = normalizeVersion(right).split(".");
|
|
26
|
+
var length = Math.max(a.length, b.length);
|
|
27
|
+
for (var i = 0; i < length; i++) {
|
|
28
|
+
var aPart = parseInt(a[i] || "0", 10);
|
|
29
|
+
var bPart = parseInt(b[i] || "0", 10);
|
|
30
|
+
if (aPart > bPart) return 1;
|
|
31
|
+
if (aPart < bPart) return -1;
|
|
32
|
+
}
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function chooseDownloadUrl(release) {
|
|
37
|
+
var assets = release && release.assets ? release.assets : [];
|
|
38
|
+
var preferredNames = [
|
|
39
|
+
/^MCPBridgeCEP(?:-[\w.-]+)?\.zxp$/i,
|
|
40
|
+
/premiere.*(?:connector|bridge).*\.zxp$/i,
|
|
41
|
+
/\.zxp$/i,
|
|
42
|
+
/premiere.*(?:connector|bridge).*\.(?:zip|dmg|exe)$/i,
|
|
43
|
+
];
|
|
44
|
+
for (var p = 0; p < preferredNames.length; p++) {
|
|
45
|
+
for (var i = 0; i < assets.length; i++) {
|
|
46
|
+
if (
|
|
47
|
+
preferredNames[p].test(assets[i].name || "") &&
|
|
48
|
+
isTrustedDownloadUrl(assets[i].browser_download_url)
|
|
49
|
+
) {
|
|
50
|
+
return assets[i].browser_download_url;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return isTrustedDownloadUrl(release && release.html_url)
|
|
55
|
+
? release.html_url
|
|
56
|
+
: RELEASES_URL;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isTrustedDownloadUrl(value) {
|
|
60
|
+
return /^https:\/\/(?:github\.com|api\.github\.com|objects\.githubusercontent\.com)\//i.test(
|
|
61
|
+
String(value || "")
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
CURRENT_VERSION: CURRENT_VERSION,
|
|
67
|
+
LATEST_RELEASE_API: LATEST_RELEASE_API,
|
|
68
|
+
RELEASES_URL: RELEASES_URL,
|
|
69
|
+
normalizeVersion: normalizeVersion,
|
|
70
|
+
compareVersions: compareVersions,
|
|
71
|
+
chooseDownloadUrl: chooseDownloadUrl,
|
|
72
|
+
isTrustedDownloadUrl: isTrustedDownloadUrl,
|
|
73
|
+
};
|
|
74
|
+
});
|