premiere-pro-mcp 1.3.0 → 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.
Files changed (41) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +124 -9
  3. package/artifacts/MCPBridgeCEP.zxp +0 -0
  4. package/cep-plugin/CSXS/manifest.xml +3 -3
  5. package/cep-plugin/index.html +18 -6
  6. package/cep-plugin/main.js +125 -1
  7. package/cep-plugin/styles.css +37 -1
  8. package/cep-plugin/updater.cjs +74 -0
  9. package/dist/advanced-feature-support.d.ts +140 -0
  10. package/dist/advanced-feature-support.js +157 -0
  11. package/dist/bridge/uxp-websocket-bridge.d.ts +61 -0
  12. package/dist/bridge/uxp-websocket-bridge.js +249 -0
  13. package/dist/index.js +24 -2
  14. package/dist/platform-capabilities.d.ts +32 -1
  15. package/dist/platform-capabilities.js +47 -2
  16. package/dist/security/capabilities.js +2 -2
  17. package/dist/server.d.ts +5 -1
  18. package/dist/server.js +13 -6
  19. package/dist/tool-capability-report.d.ts +55 -0
  20. package/dist/tool-capability-report.js +148 -0
  21. package/dist/tools/av-settings.d.ts +119 -0
  22. package/dist/tools/av-settings.js +210 -0
  23. package/dist/tools/export.d.ts +100 -0
  24. package/dist/tools/export.js +160 -2
  25. package/dist/tools/health.d.ts +206 -1
  26. package/dist/tools/health.js +49 -2
  27. package/dist/tools/recovery.d.ts +45 -0
  28. package/dist/tools/recovery.js +189 -0
  29. package/dist/tools/utility.d.ts +2 -0
  30. package/dist/tools/utility.js +30 -2
  31. package/dist/tools/uxp.d.ts +71 -0
  32. package/dist/tools/uxp.js +53 -0
  33. package/package.json +5 -2
  34. package/scripts/build-claude-desktop.mjs +71 -0
  35. package/uxp-plugin/README.md +43 -2
  36. package/uxp-plugin/commands.cjs +163 -0
  37. package/uxp-plugin/index.cjs +327 -25
  38. package/uxp-plugin/index.html +7 -6
  39. package/uxp-plugin/manifest.json +1 -1
  40. package/uxp-plugin/protocol.cjs +82 -3
  41. package/uxp-plugin/transcript.cjs +95 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,31 @@ 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
+
26
+ ## [1.3.1] - 2026-07-25
27
+
28
+ ### Fixed
29
+
30
+ - Fixed `set_sequence_frame_rate` to convert frames per second into Premiere's required
31
+ ticks-per-frame `Time` value and verify the applied setting instead of assigning a numeric frame
32
+ period that could corrupt the sequence timebase. ([#37](https://github.com/leancoderkavy/premiere-pro-mcp/issues/37))
33
+
9
34
  ## [1.3.0] - 2026-07-25
10
35
 
11
36
  ### Added
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Give AI full control over Adobe Premiere Pro.**
6
6
 
7
- 269 tools across 29 modules, 3 resources, and 4 guided workflows.
7
+ 278 tools across 31 modules, 3 resources, and 4 guided workflows.
8
8
 
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
10
  [![Node.js](https://img.shields.io/badge/Node.js-20.19%2B-green.svg)](https://nodejs.org)
@@ -25,12 +25,14 @@ 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 269 tools spanning the supported ExtendScript, QE DOM, and safe edit-planning surfaces.
28
+ The AI handles the entire workflow through 278 tools spanning the supported ExtendScript, QE DOM, and safe edit-planning surfaces.
29
29
 
30
- ### What's new in 1.3.0
30
+ ### What's new in 1.3.1
31
31
 
32
32
  - Windows npm releases now include a verified, signed CEP ZXP and install it automatically, covering
33
33
  hosts that reject the raw development bundle even when `PlayerDebugMode` is enabled.
34
+ - `set_sequence_frame_rate` now converts frames per second to Premiere ticks per frame and verifies
35
+ the applied setting instead of assigning a numeric frame period.
34
36
  - `premiere-pro-mcp --diagnose-cep` checks the installed manifest, debug-key types, and recent
35
37
  Premiere signature failures.
36
38
  - TypeScript 7, Vitest 4, Zod 4, MCP SDK 1.29, Next.js 16.2, and patched transitive dependencies
@@ -41,7 +43,7 @@ The AI handles the entire workflow through 269 tools spanning the supported Exte
41
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.
42
44
  - **Capability profiles:** unsafe scripting is disabled by default and requires explicit `unsafe-script` authority.
43
45
  - **Modern MCP responses:** tools expose safety annotations and structured results; four workflow prompts and a machine-readable workflow resource guide common edits.
44
- - **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.
45
47
 
46
48
  ---
47
49
 
@@ -215,6 +217,58 @@ Add to your VS Code MCP server configuration:
215
217
 
216
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.
217
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
+
218
272
  ### Windows and macOS capability coverage
219
273
 
220
274
  | Surface | Windows | macOS | Verification boundary |
@@ -224,7 +278,58 @@ The default bridge directory is derived from the operating system on both sides,
224
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 |
225
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 |
226
280
 
227
- `get_capabilities` reports the current operating system, temp directory, CEP/UXP coverage, enabled authority profile, and any live-host verification still required. It does not claim a Premiere operation succeeded; use `ping` and inspect each tool result for runtime evidence.
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.
228
333
 
229
334
  ---
230
335
 
@@ -268,7 +373,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
268
373
 
269
374
  ---
270
375
 
271
- ## Tools (269)
376
+ ## Tools (278)
272
377
 
273
378
  ### Discovery & Inspection (10 + 10)
274
379
 
@@ -284,6 +389,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
284
389
  | `search_project_items` | Filter by name, extension, offline status, color label |
285
390
  | `get_premiere_state` | Full snapshot: project, sequence, playhead, selection |
286
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 |
287
393
 
288
394
  ### Project Management (26)
289
395
 
@@ -339,16 +445,23 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
339
445
  | `get_value_at_time` | Query interpolated value at any time |
340
446
  | `set_color_value` | Set color properties on effects |
341
447
 
342
- ### Export & Encoding (14)
448
+ ### Export & Encoding (16)
343
449
 
344
450
  | Tool | Description |
345
451
  | :--- | :---------- |
346
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 |
347
455
  | `capture_frame` | Export frame as PNG, return as base64 image |
348
456
  | `export_as_fcp_xml` / `export_aaf` / `export_omf` | Interchange formats |
349
457
  | `encode_project_item` / `encode_file` | Direct encoding |
350
458
  | `start_batch_encode` | Start render queue |
351
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
+
352
465
  ### Source Monitor & Playback (7 + 4)
353
466
 
354
467
  | Tool | Description |
@@ -493,12 +606,13 @@ premiere-pro-mcp/
493
606
  ├── src/
494
607
  │ ├── index.ts # Entry point — stdio transport setup
495
608
  │ ├── http-server.ts # Entry point — HTTP/SSE transport (Fly.io / remote)
496
- │ ├── server.ts # MCP server — registers 269 tools + 3 resources + 4 prompts
609
+ │ ├── server.ts # MCP server — registers 278 tools + 3 resources + 4 prompts
497
610
  │ ├── bridge/
498
611
  │ │ ├── file-bridge.ts # File-based IPC (write .jsx, poll .json)
499
612
  │ │ └── script-builder.ts # ExtendScript generator with ES3 helpers
500
- │ ├── tools/ # 29 tool modules
613
+ │ ├── tools/ # 31 tool modules
501
614
  │ │ ├── discovery.ts # Project discovery and queries
615
+ │ │ ├── recovery.ts # Read-only autosave discovery and private bridge telemetry
502
616
  │ │ ├── project.ts # Project management and import
503
617
  │ │ ├── media.ts # Media and proxy management
504
618
  │ │ ├── sequence.ts # Sequence creation and settings
@@ -506,6 +620,7 @@ premiere-pro-mcp/
506
620
  │ │ ├── effects.ts # Effect application and color correction
507
621
  │ │ ├── transitions.ts # Transition management (QE DOM)
508
622
  │ │ ├── audio.ts # Audio levels and keyframes
623
+ │ │ ├── av-settings.ts # Documented AV inspection, mapping, and capability boundaries
509
624
  │ │ ├── text.ts # Text overlays and MOGRTs
510
625
  │ │ ├── markers.ts # Sequence and clip markers
511
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.3.0" ExtensionBundleName="MCP Bridge">
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.3.0"/>
5
- <Extension Id="com.mcp.premiere.bridge.headless" Version="1.3.0"/>
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>
@@ -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>
@@ -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").textContent = text;
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
  })();
@@ -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: 1px solid var(--violet); outline-offset: 2px; }
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
+ });