premiere-pro-mcp 1.3.1 → 1.5.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 (48) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +178 -17
  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/http-server.js +35 -9
  14. package/dist/index.js +28 -2
  15. package/dist/platform-capabilities.d.ts +32 -1
  16. package/dist/platform-capabilities.js +47 -2
  17. package/dist/security/capabilities.d.ts +15 -0
  18. package/dist/security/capabilities.js +24 -2
  19. package/dist/server.d.ts +13 -1
  20. package/dist/server.js +62 -8
  21. package/dist/telemetry.d.ts +8 -0
  22. package/dist/telemetry.js +63 -0
  23. package/dist/tool-capability-report.d.ts +55 -0
  24. package/dist/tool-capability-report.js +148 -0
  25. package/dist/tools/advanced.js +48 -9
  26. package/dist/tools/audio.d.ts +52 -0
  27. package/dist/tools/audio.js +224 -3
  28. package/dist/tools/av-settings.d.ts +119 -0
  29. package/dist/tools/av-settings.js +210 -0
  30. package/dist/tools/export.d.ts +100 -0
  31. package/dist/tools/export.js +160 -2
  32. package/dist/tools/health.d.ts +206 -1
  33. package/dist/tools/health.js +49 -2
  34. package/dist/tools/recovery.d.ts +45 -0
  35. package/dist/tools/recovery.js +189 -0
  36. package/dist/tools/timeline.js +108 -18
  37. package/dist/tools/track-targeting.js +47 -5
  38. package/dist/tools/uxp.d.ts +71 -0
  39. package/dist/tools/uxp.js +53 -0
  40. package/package.json +6 -2
  41. package/scripts/build-claude-desktop.mjs +71 -0
  42. package/uxp-plugin/README.md +43 -2
  43. package/uxp-plugin/commands.cjs +160 -0
  44. package/uxp-plugin/index.cjs +325 -29
  45. package/uxp-plugin/index.html +7 -6
  46. package/uxp-plugin/manifest.json +1 -1
  47. package/uxp-plugin/protocol.cjs +82 -3
  48. package/uxp-plugin/transcript.cjs +95 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,47 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.5.0] - 2026-07-30
10
+
11
+ ### Added
12
+
13
+ - Added `detect_silence` for finding dead air in local source media with FFmpeg, including
14
+ Docker support and clear local-install guidance.
15
+ - Added anonymous, opt-out PostHog usage telemetry with prompt flushing for low-volume servers.
16
+ - Added an immersive editorial landing-page experience, product demo video, changelog page, and
17
+ a 30-day launch plan.
18
+
19
+ ### Changed
20
+
21
+ - Expanded the MCP surface to 279 tools and limited advertised tools to those allowed by the
22
+ active capability profile.
23
+ - Documented capability-filtered discovery, remote media-path constraints, and the difference
24
+ between the 279 registered tools and the 277 tools available to the default profile.
25
+
26
+ ### Fixed
27
+
28
+ - Structural timeline tools now verify razor, ripple-delete, transition, and track-targeting
29
+ mutations instead of reporting success when Premiere applied only part or none of an edit.
30
+ - Server metadata now reports the package version rather than a stale hard-coded value.
31
+ - Resolved CodeQL findings in HTTP authentication and filesystem-path handling.
32
+
33
+ ## [1.4.0] - 2026-07-26
34
+
35
+ ### Added
36
+
37
+ - Added in-panel connector update discovery and trusted downloads from GitHub Releases.
38
+ - Added authenticated MCP-to-UXP WebSocket transport, transcript and caption inspection, event-driven
39
+ state reporting, operation semantics, and supported video-transition workflows.
40
+ - Added recovery diagnostics, export verification, AV inspection, capability reporting, and
41
+ collaboration/AI feature eligibility discovery.
42
+ - Added installable Codex, Claude Code, and Claude Desktop distributions.
43
+
44
+ ### Changed
45
+
46
+ - Expanded the MCP surface to 278 tools and aligned documentation, plugin metadata, and distribution
47
+ manifests with the new release.
48
+ - Added automated signed CEP connector assets and Claude Desktop bundles to GitHub releases.
49
+
9
50
  ## [1.3.1] - 2026-07-25
10
51
 
11
52
  ### Fixed
package/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  # Premiere Pro MCP Server
4
4
 
5
+ [![MCP Toplist](https://mcptoplist.com/badge/glama%2Fleancoderkavy%2Fpremiere-pro-mcp.svg)](https://mcptoplist.com/server/glama%2Fleancoderkavy%2Fpremiere-pro-mcp)
6
+
5
7
  **Give AI full control over Adobe Premiere Pro.**
6
8
 
7
- 269 tools across 29 modules, 3 resources, and 4 guided workflows.
9
+ 279 tools across 31 modules, 3 resources, and 4 guided workflows.
8
10
 
9
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
12
  [![Node.js](https://img.shields.io/badge/Node.js-20.19%2B-green.svg)](https://nodejs.org)
@@ -25,7 +27,7 @@ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that l
25
27
  "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
28
  ```
27
29
 
28
- The AI handles the entire workflow through 269 tools spanning the supported ExtendScript, QE DOM, and safe edit-planning surfaces.
30
+ The AI handles the entire workflow through 279 tools spanning the supported ExtendScript, QE DOM, local media analysis, and safe edit-planning surfaces.
29
31
 
30
32
  ### What's new in 1.3.1
31
33
 
@@ -43,12 +45,20 @@ The AI handles the entire workflow through 269 tools spanning the supported Exte
43
45
  - **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
46
  - **Capability profiles:** unsafe scripting is disabled by default and requires explicit `unsafe-script` authority.
45
47
  - **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.
48
+ - **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
49
 
48
50
  ---
49
51
 
50
52
  ## Quick Start
51
53
 
54
+ ### Before you begin
55
+
56
+ - Node.js **20.19 or newer** on Windows or macOS.
57
+ - Adobe Premiere Pro **2020–2026**. Keep Premiere, the CEP bridge, and your MCP client on the same computer for the recommended local setup.
58
+ - Optional: [ffmpeg](https://ffmpeg.org/download.html) on `PATH` for `detect_silence`
59
+ (`brew install ffmpeg` on macOS or `winget install Gyan.FFmpeg` on Windows).
60
+ The production Docker image already includes it.
61
+
52
62
  ### 1. Install
53
63
 
54
64
  **Option A — npm (recommended):**
@@ -138,6 +148,20 @@ done
138
148
 
139
149
  ### 3. Configure your MCP client
140
150
 
151
+ If you installed from npm, configure the client to run the global command:
152
+
153
+ ```json
154
+ {
155
+ "mcpServers": {
156
+ "premiere-pro": {
157
+ "command": "premiere-pro-mcp"
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ If you cloned the repository instead, use the source-build configuration shown below for your client.
164
+
141
165
  <details>
142
166
  <summary><strong>Claude Desktop</strong></summary>
143
167
 
@@ -213,10 +237,63 @@ Add to your VS Code MCP server configuration:
213
237
  1. Open (or restart) Premiere Pro
214
238
  2. The bridge starts automatically using the default temp directory (or its previously saved setting)
215
239
  3. Optionally go to **Window > Extensions > MCP Bridge** to confirm the green "Running" status or change the **Temp Directory** to match your MCP client config
216
- 4. Ask your AI assistant: *"What's my current Premiere Pro project?"*
240
+ 4. Ask your AI assistant to run `get_capabilities`, then `ping`, with Premiere open.
241
+ 5. For a safe first request, ask: *"What is my current Premiere Pro project and active sequence? Do not make changes."*
217
242
 
218
243
  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
244
 
245
+ ### Codex plugin
246
+
247
+ This repository includes an installable Codex plugin that bundles the local MCP
248
+ server with a safety-oriented Premiere editing skill.
249
+
250
+ From a clone of this repository:
251
+
252
+ ```bash
253
+ codex plugin marketplace add .
254
+ codex plugin add premiere-pro@premiere-pro-mcp
255
+ npx -y premiere-pro-mcp@1.3.1 --install-cep
256
+ ```
257
+
258
+ Restart Premiere Pro and start a new Codex session after installation. The plugin
259
+ launches `premiere-pro-mcp@1.3.1` through `npx`; the separate CEP installation is
260
+ required because the MCP server communicates with the running Premiere host through
261
+ the local bridge.
262
+
263
+ The plugin source lives in [`plugins/premiere-pro`](plugins/premiere-pro), and the
264
+ repository marketplace manifest lives in
265
+ [`.agents/plugins/marketplace.json`](.agents/plugins/marketplace.json).
266
+
267
+ ### Claude
268
+
269
+ For Claude Code, add this repository as a marketplace and install the plugin:
270
+
271
+ ```text
272
+ /plugin marketplace add leancoderkavy/premiere-pro-mcp
273
+ /plugin install premiere-pro@premiere-pro-mcp
274
+ ```
275
+
276
+ Then install the Premiere bridge and start a new Claude Code session:
277
+
278
+ ```bash
279
+ npx -y premiere-pro-mcp@1.3.1 --install-cep
280
+ ```
281
+
282
+ The Claude Code package lives in
283
+ [`claude-plugins/premiere-pro`](claude-plugins/premiere-pro), with its marketplace
284
+ at [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json).
285
+
286
+ Claude Desktop uses the self-contained MCP Bundle format, formerly called Desktop
287
+ Extensions. Build both the current `.mcpb` artifact and a legacy `.dxt` copy with:
288
+
289
+ ```bash
290
+ npm run build:claude
291
+ ```
292
+
293
+ Install the resulting file from `artifacts/` through **Settings > Extensions >
294
+ Advanced settings > Install Extension**. The Premiere CEP bridge must still be
295
+ installed separately.
296
+
220
297
  ### Windows and macOS capability coverage
221
298
 
222
299
  | Surface | Windows | macOS | Verification boundary |
@@ -224,9 +301,72 @@ The default bridge directory is derived from the operating system on both sides,
224
301
  | CEP production bridge | Premiere Pro 2020–2026 | Premiere Pro 2020–2026 | Run `get_capabilities`, then `ping` with Premiere open |
225
302
  | UXP preview bridge | Premiere Pro 25.6+ | Premiere Pro 25.6+ | Live loopback WebSocket and host API verification required |
226
303
  | 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
- | CI build and unit tests | Node 18 and 22 | Node 18 and 22 | GitHub-hosted OS runners; no Adobe host is available in CI |
304
+ | CI build and unit tests | Node 20, 22, and 24 | Node 20, 22, and 24 | GitHub-hosted OS runners; no Adobe host is available in CI |
305
+
306
+ `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 the full `tools` catalog generated from the tools registered by the server, including tools disabled by the active profile. Every entry identifies:
307
+
308
+ - the execution backend (`local`, CEP/ExtendScript, QE, or orchestrator);
309
+ - static support status (`supported`, `limited`, `experimental`, or `unsupported`);
310
+ - the minimum Premiere version known to the server;
311
+ - the required authority and whether the current profile enables it;
312
+ - the verification boundary and whether a live Premiere host is required; and
313
+ - relevant operational notes.
314
+
315
+ 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.
316
+
317
+ MCP `tools/list` is filtered to the active authority profile. The default
318
+ `inspect,edit,export,filesystem` profile advertises 277 of the 279 registered
319
+ tools and omits `execute_extendscript` and `evaluate_expression`, which require
320
+ explicit `unsafe-script` authority. `ping` and `get_capabilities` remain visible
321
+ under every profile so a restricted or misconfigured server can still explain
322
+ its state. The call-time capability guard remains authoritative even if listing
323
+ metadata is wrong.
324
+
325
+ The MCP handshake reads `serverInfo.version` from the installed `package.json`,
326
+ so clients receive the package version that is actually running rather than a
327
+ separately maintained literal.
328
+
329
+ 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.
330
+
331
+ ### Collaboration and AI feature boundaries
332
+
333
+ `get_advanced_feature_support` returns a machine-readable matrix for Productions,
334
+ Team Projects, Frame.io, Media Intelligence, Generative Extend, Object Mask,
335
+ caption translation, Speech-to-Text, Enhance Speech, and Remix. Pass an optional
336
+ Premiere version, intended backend, confirmed entitlements, and network state to
337
+ evaluate prerequisites without conflating them with API availability. It
338
+ distinguishes documented APIs from entitlements, network prerequisites, separate
339
+ service APIs, and user-assisted operations without using menu automation or
340
+ private APIs.
341
+
342
+ The report tool itself is local: it does not contact Premiere and is callable
343
+ through the current MCP server. Each feature entry separately reports whether
344
+ its operations are callable through the production CEP transport. Productions
345
+ reports only static backend/version eligibility until a UXP host performs live
346
+ capability negotiation.
347
+
348
+ - Productions exposes documented read-only state through UXP, but the production
349
+ MCP transport is still CEP.
350
+ - Frame.io needs a separately authenticated Frame.io API integration; an account
351
+ entitlement alone does not make it callable through Premiere's DOM.
352
+ - Transcript JSON import/export is documented in UXP. Starting Speech-to-Text is not.
353
+ - The remaining AI operations are user-assisted or unsupported by documented
354
+ public APIs. The tool explains what can be inspected after a user completes
355
+ the operation and where artifact provenance cannot be established safely.
356
+ - The server never uses menu automation, private APIs, clip-name heuristics, or
357
+ duration changes as proof that an AI operation occurred.
358
+
359
+ ### Authenticated UXP connection
360
+
361
+ The MCP server can accept a local UXP panel connection and invoke the UXP commands that are currently implemented:
362
+
363
+ ```bash
364
+ PREMIERE_UXP_TOKEN="replace-with-a-long-random-secret" premiere-pro-mcp
365
+ ```
366
+
367
+ 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.
228
368
 
229
- `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.
369
+ 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
370
 
231
371
  ---
232
372
 
@@ -270,7 +410,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
270
410
 
271
411
  ---
272
412
 
273
- ## Tools (269)
413
+ ## Tools (279 total; 277 under the default profile)
274
414
 
275
415
  ### Discovery & Inspection (10 + 10)
276
416
 
@@ -286,6 +426,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
286
426
  | `search_project_items` | Filter by name, extension, offline status, color label |
287
427
  | `get_premiere_state` | Full snapshot: project, sequence, playhead, selection |
288
428
  | `inspect_dom_object` | Explore any Premiere Pro DOM object interactively |
429
+ | `get_advanced_feature_support` | Collaboration/AI API support, prerequisites, entitlements, and user-assisted boundaries |
289
430
 
290
431
  ### Project Management (26)
291
432
 
@@ -341,16 +482,23 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
341
482
  | `get_value_at_time` | Query interpolated value at any time |
342
483
  | `set_color_value` | Set color properties on effects |
343
484
 
344
- ### Export & Encoding (14)
485
+ ### Export & Encoding (16)
345
486
 
346
487
  | Tool | Description |
347
488
  | :--- | :---------- |
348
489
  | `export_sequence` | Export via Adobe Media Encoder |
490
+ | `validate_export_preset` | Validate an `.epr` file and resolve its output extension in Premiere |
491
+ | `verify_delivery_file` | Verify output size and calculate SHA-256/SHA-512 checksums |
349
492
  | `capture_frame` | Export frame as PNG, return as base64 image |
350
493
  | `export_as_fcp_xml` / `export_aaf` / `export_omf` | Interchange formats |
351
494
  | `encode_project_item` / `encode_file` | Direct encoding |
352
495
  | `start_batch_encode` | Start render queue |
353
496
 
497
+ Premiere's documented automation surfaces do not currently expose OTIO or EDL
498
+ interchange, Render and Replace, cloud publishing, or Content Credentials export
499
+ configuration. `get_capabilities` reports these delivery gaps explicitly rather
500
+ than presenting UI-only operations as available tools.
501
+
354
502
  ### Source Monitor & Playback (7 + 4)
355
503
 
356
504
  | Tool | Description |
@@ -396,13 +544,12 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
396
544
  | `get_workspaces` / `set_workspace` | Switch workspace layouts |
397
545
  | `create_caption_track` | Create caption/subtitle tracks |
398
546
 
399
- ### Scripting (6)
547
+ ### Scripting (2)
400
548
 
401
549
  | Tool | Description |
402
550
  | :--- | :----------- |
403
- | `execute_extendscript` | Run arbitrary ExtendScript (ES3) |
404
- | `evaluate_expression` | Quick one-line eval |
405
- | `send_raw_script` | Bypass security validation (advanced) |
551
+ | `execute_extendscript` | Run arbitrary ExtendScript (ES3); requires explicit `unsafe-script` authority |
552
+ | `evaluate_expression` | Evaluate a one-line expression; requires explicit `unsafe-script` authority |
406
553
 
407
554
  ### ...and 100+ more
408
555
 
@@ -470,6 +617,7 @@ Then connect with:
470
617
  ```
471
618
 
472
619
  > **Note:** The file bridge still requires the CEP plugin to share the same `PREMIERE_TEMP_DIR`. For cloud deployments this means running a sync agent or using `fly proxy` / WireGuard to reach your local machine.
620
+ > `detect_silence` can analyze only media paths available inside the server filesystem; a desktop-only path is not automatically available to a remote Fly machine.
473
621
 
474
622
  ---
475
623
 
@@ -485,6 +633,16 @@ Then connect with:
485
633
  | `PORT` | HTTP port (HTTP/SSE transport only) | `3000` |
486
634
  | `MCP_AUTH_TOKEN` | Bearer token required by the HTTP transport | unset |
487
635
  | `ALLOW_UNAUTHENTICATED` | Set to `1` to run HTTP without auth (unsafe; throwaway instances only) | unset |
636
+ | `POSTHOG_API_KEY` | PostHog project token; enables privacy-safe MCP usage telemetry | unset |
637
+ | `POSTHOG_HOST` | PostHog ingestion host | `https://us.i.posthog.com` |
638
+ | `POSTHOG_ENVIRONMENT` | Environment property attached to telemetry events | `production` |
639
+ | `POSTHOG_DISTINCT_ID` | Optional stable anonymous server identifier | Fly machine ID or random boot ID |
640
+
641
+ When PostHog is enabled, the server records `mcp_connection_attempt`,
642
+ `mcp_request`, and `mcp_tool_call`. Events contain operational fields such as
643
+ method, tool name, outcome, status code, and duration. Authentication tokens,
644
+ IP addresses, MCP arguments, project paths, media names, and tool results are
645
+ never sent. Person profiles are disabled for these events.
488
646
 
489
647
  ---
490
648
 
@@ -495,19 +653,21 @@ premiere-pro-mcp/
495
653
  ├── src/
496
654
  │ ├── index.ts # Entry point — stdio transport setup
497
655
  │ ├── http-server.ts # Entry point — HTTP/SSE transport (Fly.io / remote)
498
- │ ├── server.ts # MCP server — registers 269 tools + 3 resources + 4 prompts
656
+ │ ├── server.ts # MCP server — registers 279 tools, filtered by authority profile
499
657
  │ ├── bridge/
500
658
  │ │ ├── file-bridge.ts # File-based IPC (write .jsx, poll .json)
501
659
  │ │ └── script-builder.ts # ExtendScript generator with ES3 helpers
502
- │ ├── tools/ # 29 tool modules
660
+ │ ├── tools/ # 31 tool modules
503
661
  │ │ ├── discovery.ts # Project discovery and queries
662
+ │ │ ├── recovery.ts # Read-only autosave discovery and private bridge telemetry
504
663
  │ │ ├── project.ts # Project management and import
505
664
  │ │ ├── media.ts # Media and proxy management
506
665
  │ │ ├── sequence.ts # Sequence creation and settings
507
666
  │ │ ├── timeline.ts # Timeline clip operations
508
667
  │ │ ├── effects.ts # Effect application and color correction
509
668
  │ │ ├── transitions.ts # Transition management (QE DOM)
510
- │ │ ├── audio.ts # Audio levels and keyframes
669
+ │ │ ├── audio.ts # Audio levels, keyframes, and ffmpeg silence analysis
670
+ │ │ ├── av-settings.ts # Documented AV inspection, mapping, and capability boundaries
511
671
  │ │ ├── text.ts # Text overlays and MOGRTs
512
672
  │ │ ├── markers.ts # Sequence and clip markers
513
673
  │ │ ├── tracks.ts # Track add/delete/lock/visibility
@@ -562,8 +722,9 @@ All generated scripts use **ES3 syntax** (`var`, manual `for` loops, no arrow fu
562
722
  ### Security
563
723
 
564
724
  Understand the trust model before deploying this: **any client that can reach the MCP
565
- server can control Premiere Pro.** `execute_extendscript` and `send_raw_script` are
566
- arbitrary-code-execution tools by design and are disabled by default. Enable them only by setting
725
+ server can control Premiere Pro.** `execute_extendscript` and `evaluate_expression` are
726
+ arbitrary-code-execution tools by design and are omitted from discovery and denied at call time
727
+ by default. Enable them only by setting
567
728
  `PREMIERE_MCP_CAPABILITIES=inspect,edit,export,filesystem,unsafe-script`.
568
729
 
569
730
  - **Run it locally over stdio** unless you have a specific reason not to. That's the safe default.
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.1" ExtensionBundleName="MCP Bridge">
2
+ <ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.5.0" ExtensionBundleName="MCP Bridge">
3
3
  <ExtensionList>
4
- <Extension Id="com.mcp.premiere.bridge.panel" Version="1.3.1"/>
5
- <Extension Id="com.mcp.premiere.bridge.headless" Version="1.3.1"/>
4
+ <Extension Id="com.mcp.premiere.bridge.panel" Version="1.5.0"/>
5
+ <Extension Id="com.mcp.premiere.bridge.headless" Version="1.5.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.5.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
+ }