premiere-pro-mcp 1.4.0 → 1.6.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 +48 -0
- package/README.md +78 -27
- package/artifacts/MCPBridgeCEP.zxp +0 -0
- package/cep-plugin/CSXS/manifest.xml +3 -3
- package/cep-plugin/index.html +1 -1
- package/cep-plugin/updater.cjs +1 -1
- package/dist/http-server.js +35 -9
- package/dist/index.js +6 -2
- package/dist/security/capabilities.d.ts +15 -0
- package/dist/security/capabilities.js +23 -1
- package/dist/server.d.ts +8 -0
- package/dist/server.js +49 -2
- package/dist/telemetry.d.ts +8 -0
- package/dist/telemetry.js +63 -0
- package/dist/tools/advanced.js +48 -9
- package/dist/tools/audio.d.ts +52 -0
- package/dist/tools/audio.js +224 -3
- package/dist/tools/project.js +25 -3
- package/dist/tools/timeline.js +108 -18
- package/dist/tools/track-targeting.js +47 -5
- package/dist/tools/uxp.d.ts +197 -0
- package/dist/tools/uxp.js +86 -0
- package/package.json +5 -4
- package/scripts/build-claude-desktop.mjs +20 -4
- package/uxp-plugin/commands.cjs +126 -13
- package/uxp-plugin/index.cjs +5 -11
- package/uxp-plugin/manifest.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,54 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.6.0] - 2026-07-31
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added a capability-aware UXP foundation for revisioned project inspection, verified saves,
|
|
14
|
+
preset-based sequence creation, OTIO/FCP XML interchange, transcript-language discovery,
|
|
15
|
+
Object Mask detection, and Adobe Media Encoder controls on compatible Premiere hosts.
|
|
16
|
+
- Added explicit UXP operation outcomes and bounded operation-ID replay protection so a client retry
|
|
17
|
+
does not repeat a completed command within the same panel session.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Documented the 10 UXP MCP tools that become available when an authenticated local panel is
|
|
22
|
+
connected, including their host-version and live-verification boundaries.
|
|
23
|
+
- Updated the MCP SDK and Node type dependencies and GitHub Actions artifact actions.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `create_project` now rejects directory paths and verifies that Premiere switched to the exact
|
|
28
|
+
requested `.prproj` path before reporting success, preventing edits from continuing in a
|
|
29
|
+
previously open project after a failed creation attempt.
|
|
30
|
+
- Claude Desktop bundle packaging now invokes npm through the active Node executable so the
|
|
31
|
+
release build works on Windows where `npm` is exposed as a command shim.
|
|
32
|
+
|
|
33
|
+
## [1.5.0] - 2026-07-30
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Added `detect_silence` for finding dead air in local source media with FFmpeg, including
|
|
38
|
+
Docker support and clear local-install guidance.
|
|
39
|
+
- Added anonymous, opt-out PostHog usage telemetry with prompt flushing for low-volume servers.
|
|
40
|
+
- Added an immersive editorial landing-page experience, product demo video, changelog page, and
|
|
41
|
+
a 30-day launch plan.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- Expanded the MCP surface to 279 tools and limited advertised tools to those allowed by the
|
|
46
|
+
active capability profile.
|
|
47
|
+
- Documented capability-filtered discovery, remote media-path constraints, and the difference
|
|
48
|
+
between the 279 registered tools and the 277 tools available to the default profile.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- Structural timeline tools now verify razor, ripple-delete, transition, and track-targeting
|
|
53
|
+
mutations instead of reporting success when Premiere applied only part or none of an edit.
|
|
54
|
+
- Server metadata now reports the package version rather than a stale hard-coded value.
|
|
55
|
+
- Resolved CodeQL findings in HTTP authentication and filesystem-path handling.
|
|
56
|
+
|
|
9
57
|
## [1.4.0] - 2026-07-26
|
|
10
58
|
|
|
11
59
|
### Added
|
package/README.md
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
# Premiere Pro MCP Server
|
|
4
4
|
|
|
5
|
+
[](https://mcptoplist.com/server/glama%2Fleancoderkavy%2Fpremiere-pro-mcp)
|
|
6
|
+
|
|
5
7
|
**Give AI full control over Adobe Premiere Pro.**
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
279 core tools across 31 modules, 3 resources, and 4 guided workflows. A connected UXP host adds 10 capability-gated tools.
|
|
8
10
|
|
|
9
11
|
[](LICENSE)
|
|
10
12
|
[](https://nodejs.org)
|
|
@@ -25,18 +27,14 @@ 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
|
|
30
|
+
The AI handles the entire workflow through 279 core tools spanning the supported ExtendScript, QE DOM, local media analysis, and safe edit-planning surfaces. A compatible, authenticated UXP panel adds 10 documented, capability-gated workflows without replacing the production CEP bridge.
|
|
29
31
|
|
|
30
|
-
### What's new in 1.
|
|
32
|
+
### What's new in 1.6.0
|
|
31
33
|
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
- `
|
|
35
|
-
|
|
36
|
-
- `premiere-pro-mcp --diagnose-cep` checks the installed manifest, debug-key types, and recent
|
|
37
|
-
Premiere signature failures.
|
|
38
|
-
- TypeScript 7, Vitest 4, Zod 4, MCP SDK 1.29, Next.js 16.2, and patched transitive dependencies
|
|
39
|
-
modernize the toolchain and remove production audit findings.
|
|
34
|
+
- **Capability-aware UXP foundation:** compatible Premiere 25.6-26.3 hosts can expose revisioned project inspection, verified saves, preset sequence creation, OTIO/FCP XML interchange, transcript-language discovery, Object Mask detection, and Adobe Media Encoder controls.
|
|
35
|
+
- **Retry-safe UXP mutations:** optional operation IDs prevent a client retry from repeating a completed command in the same panel session, while each command reports `verified` or `committed_unverified` evidence honestly.
|
|
36
|
+
- **Safe project creation:** `create_project` rejects directory paths and verifies Premiere opened the requested `.prproj` before reporting success.
|
|
37
|
+
- **Current distribution metadata:** the CEP/UXP panels, Codex and Claude plugins, landing page, and npm package now all identify v1.6.0.
|
|
40
38
|
|
|
41
39
|
### Added in 1.2.0
|
|
42
40
|
|
|
@@ -49,6 +47,14 @@ The AI handles the entire workflow through 278 tools spanning the supported Exte
|
|
|
49
47
|
|
|
50
48
|
## Quick Start
|
|
51
49
|
|
|
50
|
+
### Before you begin
|
|
51
|
+
|
|
52
|
+
- Node.js **20.19 or newer** on Windows or macOS.
|
|
53
|
+
- Adobe Premiere Pro **2020–2026**. Keep Premiere, the CEP bridge, and your MCP client on the same computer for the recommended local setup.
|
|
54
|
+
- Optional: [ffmpeg](https://ffmpeg.org/download.html) on `PATH` for `detect_silence`
|
|
55
|
+
(`brew install ffmpeg` on macOS or `winget install Gyan.FFmpeg` on Windows).
|
|
56
|
+
The production Docker image already includes it.
|
|
57
|
+
|
|
52
58
|
### 1. Install
|
|
53
59
|
|
|
54
60
|
**Option A — npm (recommended):**
|
|
@@ -138,6 +144,20 @@ done
|
|
|
138
144
|
|
|
139
145
|
### 3. Configure your MCP client
|
|
140
146
|
|
|
147
|
+
If you installed from npm, configure the client to run the global command:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"mcpServers": {
|
|
152
|
+
"premiere-pro": {
|
|
153
|
+
"command": "premiere-pro-mcp"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
If you cloned the repository instead, use the source-build configuration shown below for your client.
|
|
160
|
+
|
|
141
161
|
<details>
|
|
142
162
|
<summary><strong>Claude Desktop</strong></summary>
|
|
143
163
|
|
|
@@ -213,7 +233,8 @@ Add to your VS Code MCP server configuration:
|
|
|
213
233
|
1. Open (or restart) Premiere Pro
|
|
214
234
|
2. The bridge starts automatically using the default temp directory (or its previously saved setting)
|
|
215
235
|
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
|
|
236
|
+
4. Ask your AI assistant to run `get_capabilities`, then `ping`, with Premiere open.
|
|
237
|
+
5. For a safe first request, ask: *"What is my current Premiere Pro project and active sequence? Do not make changes."*
|
|
217
238
|
|
|
218
239
|
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
240
|
|
|
@@ -227,11 +248,11 @@ From a clone of this repository:
|
|
|
227
248
|
```bash
|
|
228
249
|
codex plugin marketplace add .
|
|
229
250
|
codex plugin add premiere-pro@premiere-pro-mcp
|
|
230
|
-
npx -y premiere-pro-mcp@1.
|
|
251
|
+
npx -y premiere-pro-mcp@1.6.0 --install-cep
|
|
231
252
|
```
|
|
232
253
|
|
|
233
254
|
Restart Premiere Pro and start a new Codex session after installation. The plugin
|
|
234
|
-
launches `premiere-pro-mcp@1.
|
|
255
|
+
launches `premiere-pro-mcp@1.6.0` through `npx`; the separate CEP installation is
|
|
235
256
|
required because the MCP server communicates with the running Premiere host through
|
|
236
257
|
the local bridge.
|
|
237
258
|
|
|
@@ -251,7 +272,7 @@ For Claude Code, add this repository as a marketplace and install the plugin:
|
|
|
251
272
|
Then install the Premiere bridge and start a new Claude Code session:
|
|
252
273
|
|
|
253
274
|
```bash
|
|
254
|
-
npx -y premiere-pro-mcp@1.
|
|
275
|
+
npx -y premiere-pro-mcp@1.6.0 --install-cep
|
|
255
276
|
```
|
|
256
277
|
|
|
257
278
|
The Claude Code package lives in
|
|
@@ -276,9 +297,9 @@ installed separately.
|
|
|
276
297
|
| CEP production bridge | Premiere Pro 2020–2026 | Premiere Pro 2020–2026 | Run `get_capabilities`, then `ping` with Premiere open |
|
|
277
298
|
| UXP preview bridge | Premiere Pro 25.6+ | Premiere Pro 25.6+ | Live loopback WebSocket and host API verification required |
|
|
278
299
|
| npm CEP installer | Copies plugin and verifies `REG_SZ` debug keys | Copies plugin and verifies the installed manifest/debug settings | Restart Premiere after installation |
|
|
279
|
-
| CI build and unit tests | Node
|
|
300
|
+
| 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 |
|
|
280
301
|
|
|
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
|
|
302
|
+
`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:
|
|
282
303
|
|
|
283
304
|
- the execution backend (`local`, CEP/ExtendScript, QE, or orchestrator);
|
|
284
305
|
- static support status (`supported`, `limited`, `experimental`, or `unsupported`);
|
|
@@ -289,6 +310,18 @@ installed separately.
|
|
|
289
310
|
|
|
290
311
|
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
312
|
|
|
313
|
+
MCP `tools/list` is filtered to the active authority profile. The default
|
|
314
|
+
`inspect,edit,export,filesystem` profile advertises 277 of the 279 registered
|
|
315
|
+
tools and omits `execute_extendscript` and `evaluate_expression`, which require
|
|
316
|
+
explicit `unsafe-script` authority. `ping` and `get_capabilities` remain visible
|
|
317
|
+
under every profile so a restricted or misconfigured server can still explain
|
|
318
|
+
its state. The call-time capability guard remains authoritative even if listing
|
|
319
|
+
metadata is wrong.
|
|
320
|
+
|
|
321
|
+
The MCP handshake reads `serverInfo.version` from the installed `package.json`,
|
|
322
|
+
so clients receive the package version that is actually running rather than a
|
|
323
|
+
separately maintained literal.
|
|
324
|
+
|
|
292
325
|
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
326
|
|
|
294
327
|
### Collaboration and AI feature boundaries
|
|
@@ -329,7 +362,14 @@ PREMIERE_UXP_TOKEN="replace-with-a-long-random-secret" premiere-pro-mcp
|
|
|
329
362
|
|
|
330
363
|
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
364
|
|
|
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.
|
|
365
|
+
When enabled, MCP discovery includes `get_uxp_capabilities`, `get_uxp_state`, `inspect_project_uxp`, `save_project_uxp`, `create_sequence_with_preset_uxp`, `export_interchange_uxp`, `get_transcript_languages_uxp`, `detect_object_masks_uxp`, `configure_encoder_uxp`, and `export_frame_uxp`. Commands are advertised only while the authenticated local UXP bridge is connected; the host capability handshake remains the authority for support in the running Premiere build. A failed UXP command is never silently retried through CEP because the first operation may have partially succeeded.
|
|
366
|
+
|
|
367
|
+
Premiere 26.2-26.3 hosts also expose documented UXP workflows for revisioned project
|
|
368
|
+
inspection, verified project saves, preset-based sequence creation, OTIO/FCP XML
|
|
369
|
+
interchange, transcript-language discovery, Object Mask detection, and Adobe Media
|
|
370
|
+
Encoder control. Mutations accept optional idempotency keys and return explicit
|
|
371
|
+
verification outcomes. See [the UXP capability foundation](docs/uxp-capability-foundation.md)
|
|
372
|
+
for the command matrix and live-host validation boundary.
|
|
333
373
|
|
|
334
374
|
---
|
|
335
375
|
|
|
@@ -373,7 +413,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
373
413
|
|
|
374
414
|
---
|
|
375
415
|
|
|
376
|
-
## Tools (
|
|
416
|
+
## Tools (279 core total; 277 under the default profile; 287 with a connected UXP bridge)
|
|
377
417
|
|
|
378
418
|
### Discovery & Inspection (10 + 10)
|
|
379
419
|
|
|
@@ -507,13 +547,12 @@ than presenting UI-only operations as available tools.
|
|
|
507
547
|
| `get_workspaces` / `set_workspace` | Switch workspace layouts |
|
|
508
548
|
| `create_caption_track` | Create caption/subtitle tracks |
|
|
509
549
|
|
|
510
|
-
### Scripting (
|
|
550
|
+
### Scripting (2)
|
|
511
551
|
|
|
512
552
|
| Tool | Description |
|
|
513
553
|
| :--- | :----------- |
|
|
514
|
-
| `execute_extendscript` | Run arbitrary ExtendScript (ES3) |
|
|
515
|
-
| `evaluate_expression` |
|
|
516
|
-
| `send_raw_script` | Bypass security validation (advanced) |
|
|
554
|
+
| `execute_extendscript` | Run arbitrary ExtendScript (ES3); requires explicit `unsafe-script` authority |
|
|
555
|
+
| `evaluate_expression` | Evaluate a one-line expression; requires explicit `unsafe-script` authority |
|
|
517
556
|
|
|
518
557
|
### ...and 100+ more
|
|
519
558
|
|
|
@@ -581,6 +620,7 @@ Then connect with:
|
|
|
581
620
|
```
|
|
582
621
|
|
|
583
622
|
> **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.
|
|
623
|
+
> `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.
|
|
584
624
|
|
|
585
625
|
---
|
|
586
626
|
|
|
@@ -596,6 +636,16 @@ Then connect with:
|
|
|
596
636
|
| `PORT` | HTTP port (HTTP/SSE transport only) | `3000` |
|
|
597
637
|
| `MCP_AUTH_TOKEN` | Bearer token required by the HTTP transport | unset |
|
|
598
638
|
| `ALLOW_UNAUTHENTICATED` | Set to `1` to run HTTP without auth (unsafe; throwaway instances only) | unset |
|
|
639
|
+
| `POSTHOG_API_KEY` | PostHog project token; enables privacy-safe MCP usage telemetry | unset |
|
|
640
|
+
| `POSTHOG_HOST` | PostHog ingestion host | `https://us.i.posthog.com` |
|
|
641
|
+
| `POSTHOG_ENVIRONMENT` | Environment property attached to telemetry events | `production` |
|
|
642
|
+
| `POSTHOG_DISTINCT_ID` | Optional stable anonymous server identifier | Fly machine ID or random boot ID |
|
|
643
|
+
|
|
644
|
+
When PostHog is enabled, the server records `mcp_connection_attempt`,
|
|
645
|
+
`mcp_request`, and `mcp_tool_call`. Events contain operational fields such as
|
|
646
|
+
method, tool name, outcome, status code, and duration. Authentication tokens,
|
|
647
|
+
IP addresses, MCP arguments, project paths, media names, and tool results are
|
|
648
|
+
never sent. Person profiles are disabled for these events.
|
|
599
649
|
|
|
600
650
|
---
|
|
601
651
|
|
|
@@ -606,7 +656,7 @@ premiere-pro-mcp/
|
|
|
606
656
|
├── src/
|
|
607
657
|
│ ├── index.ts # Entry point — stdio transport setup
|
|
608
658
|
│ ├── http-server.ts # Entry point — HTTP/SSE transport (Fly.io / remote)
|
|
609
|
-
│ ├── server.ts # MCP server — registers
|
|
659
|
+
│ ├── server.ts # MCP server — registers 279 tools, filtered by authority profile
|
|
610
660
|
│ ├── bridge/
|
|
611
661
|
│ │ ├── file-bridge.ts # File-based IPC (write .jsx, poll .json)
|
|
612
662
|
│ │ └── script-builder.ts # ExtendScript generator with ES3 helpers
|
|
@@ -619,7 +669,7 @@ premiere-pro-mcp/
|
|
|
619
669
|
│ │ ├── timeline.ts # Timeline clip operations
|
|
620
670
|
│ │ ├── effects.ts # Effect application and color correction
|
|
621
671
|
│ │ ├── transitions.ts # Transition management (QE DOM)
|
|
622
|
-
│ │ ├── audio.ts # Audio levels and
|
|
672
|
+
│ │ ├── audio.ts # Audio levels, keyframes, and ffmpeg silence analysis
|
|
623
673
|
│ │ ├── av-settings.ts # Documented AV inspection, mapping, and capability boundaries
|
|
624
674
|
│ │ ├── text.ts # Text overlays and MOGRTs
|
|
625
675
|
│ │ ├── markers.ts # Sequence and clip markers
|
|
@@ -675,8 +725,9 @@ All generated scripts use **ES3 syntax** (`var`, manual `for` loops, no arrow fu
|
|
|
675
725
|
### Security
|
|
676
726
|
|
|
677
727
|
Understand the trust model before deploying this: **any client that can reach the MCP
|
|
678
|
-
server can control Premiere Pro.** `execute_extendscript` and `
|
|
679
|
-
arbitrary-code-execution tools by design and are
|
|
728
|
+
server can control Premiere Pro.** `execute_extendscript` and `evaluate_expression` are
|
|
729
|
+
arbitrary-code-execution tools by design and are omitted from discovery and denied at call time
|
|
730
|
+
by default. Enable them only by setting
|
|
680
731
|
`PREMIERE_MCP_CAPABILITIES=inspect,edit,export,filesystem,unsafe-script`.
|
|
681
732
|
|
|
682
733
|
- **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.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.6.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.6.0"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.6.0"/>
|
|
6
6
|
</ExtensionList>
|
|
7
7
|
<ExecutionEnvironment>
|
|
8
8
|
<HostList>
|
package/cep-plugin/index.html
CHANGED
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
<section class="update-section" aria-live="polite">
|
|
66
66
|
<div class="update-copy">
|
|
67
67
|
<span class="section-label">Connector updates</span>
|
|
68
|
-
<strong id="updateTitle">Version 1.
|
|
68
|
+
<strong id="updateTitle">Version 1.6.0</strong>
|
|
69
69
|
<span id="updateDetail">Checking for updates…</span>
|
|
70
70
|
</div>
|
|
71
71
|
<button id="btnUpdate" class="button button-update" onclick="handleUpdateClick()" type="button" disabled>
|
package/cep-plugin/updater.cjs
CHANGED
package/dist/http-server.js
CHANGED
|
@@ -28,6 +28,7 @@ import { fileURLToPath } from "node:url";
|
|
|
28
28
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
29
29
|
import { createServer } from "./server.js";
|
|
30
30
|
import { cleanupTempDir, getTempDir } from "./bridge/file-bridge.js";
|
|
31
|
+
import { getTelemetry } from "./telemetry.js";
|
|
31
32
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
32
33
|
const LANDING_DIR = path.resolve(__dirname, "../landing-dist");
|
|
33
34
|
const MIME = {
|
|
@@ -36,6 +37,7 @@ const MIME = {
|
|
|
36
37
|
".css": "text/css; charset=utf-8",
|
|
37
38
|
".json": "application/json",
|
|
38
39
|
".png": "image/png",
|
|
40
|
+
".mp4": "video/mp4",
|
|
39
41
|
".svg": "image/svg+xml",
|
|
40
42
|
".ico": "image/x-icon",
|
|
41
43
|
".woff2": "font/woff2",
|
|
@@ -96,6 +98,8 @@ const bridgeOptions = {
|
|
|
96
98
|
? parseInt(process.env.PREMIERE_TIMEOUT_MS, 10)
|
|
97
99
|
: undefined,
|
|
98
100
|
};
|
|
101
|
+
process.env.PREMIERE_MCP_TRANSPORT = "http";
|
|
102
|
+
const telemetry = getTelemetry();
|
|
99
103
|
const tempDir = getTempDir(bridgeOptions);
|
|
100
104
|
console.error(`[premiere-pro-mcp] Starting HTTP server on port ${PORT}...`);
|
|
101
105
|
console.error(`[premiere-pro-mcp] Temp directory: ${tempDir}`);
|
|
@@ -118,11 +122,20 @@ const httpServer = http.createServer(async (req, res) => {
|
|
|
118
122
|
}
|
|
119
123
|
// Bearer token auth (constant-time; required unless ALLOW_UNAUTHENTICATED=1)
|
|
120
124
|
if (!isAuthorized(req)) {
|
|
125
|
+
telemetry.capture("mcp_connection_attempt", {
|
|
126
|
+
outcome: "unauthorized",
|
|
127
|
+
method: req.method ?? "unknown",
|
|
128
|
+
});
|
|
121
129
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
122
130
|
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
123
131
|
return;
|
|
124
132
|
}
|
|
125
|
-
const
|
|
133
|
+
const requestStartedAt = Date.now();
|
|
134
|
+
telemetry.capture("mcp_connection_attempt", {
|
|
135
|
+
outcome: "authorized",
|
|
136
|
+
method: req.method ?? "unknown",
|
|
137
|
+
});
|
|
138
|
+
const mcpServer = createServer(bridgeOptions, { telemetry });
|
|
126
139
|
const transport = new StreamableHTTPServerTransport({
|
|
127
140
|
sessionIdGenerator: undefined, // stateless
|
|
128
141
|
});
|
|
@@ -133,8 +146,21 @@ const httpServer = http.createServer(async (req, res) => {
|
|
|
133
146
|
try {
|
|
134
147
|
await mcpServer.connect(transport);
|
|
135
148
|
await transport.handleRequest(req, res);
|
|
149
|
+
telemetry.capture("mcp_request", {
|
|
150
|
+
outcome: res.statusCode >= 400 ? "failed" : "succeeded",
|
|
151
|
+
method: req.method ?? "unknown",
|
|
152
|
+
status_code: res.statusCode,
|
|
153
|
+
duration_ms: Date.now() - requestStartedAt,
|
|
154
|
+
});
|
|
136
155
|
}
|
|
137
156
|
catch (err) {
|
|
157
|
+
telemetry.capture("mcp_request", {
|
|
158
|
+
outcome: "failed",
|
|
159
|
+
method: req.method ?? "unknown",
|
|
160
|
+
status_code: 500,
|
|
161
|
+
duration_ms: Date.now() - requestStartedAt,
|
|
162
|
+
error_type: err instanceof Error ? err.name : "UnknownError",
|
|
163
|
+
});
|
|
138
164
|
console.error("[premiere-pro-mcp] Request error:", err);
|
|
139
165
|
if (!res.headersSent) {
|
|
140
166
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -152,12 +178,12 @@ httpServer.listen(PORT, "0.0.0.0", () => {
|
|
|
152
178
|
console.error(`[premiere-pro-mcp] Auth: DISABLED via ALLOW_UNAUTHENTICATED — anyone can drive this server`);
|
|
153
179
|
}
|
|
154
180
|
});
|
|
155
|
-
|
|
156
|
-
console.error(
|
|
157
|
-
httpServer.close(
|
|
158
|
-
|
|
159
|
-
process.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
181
|
+
async function shutdown(signal) {
|
|
182
|
+
console.error(`[premiere-pro-mcp] ${signal} received, shutting down...`);
|
|
183
|
+
httpServer.close();
|
|
184
|
+
await telemetry.shutdown();
|
|
185
|
+
process.exit(0);
|
|
186
|
+
}
|
|
187
|
+
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
188
|
+
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
163
189
|
//# sourceMappingURL=http-server.js.map
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { createServer } from "./server.js";
|
|
4
4
|
import { cleanupTempDir, getTempDir } from "./bridge/file-bridge.js";
|
|
5
|
+
import { getTelemetry } from "./telemetry.js";
|
|
5
6
|
import { execFileSync } from "child_process";
|
|
6
7
|
import { fileURLToPath } from "url";
|
|
7
8
|
import path from "path";
|
|
@@ -19,7 +20,7 @@ function debugLog(message) {
|
|
|
19
20
|
const args = process.argv.slice(2);
|
|
20
21
|
if (args.includes("--help") || args.includes("-h")) {
|
|
21
22
|
console.log(`
|
|
22
|
-
premiere-pro-mcp — MCP server for Adobe Premiere Pro (
|
|
23
|
+
premiere-pro-mcp — MCP server for Adobe Premiere Pro (279 tools)
|
|
23
24
|
|
|
24
25
|
Usage:
|
|
25
26
|
premiere-pro-mcp Start the MCP server (stdio transport)
|
|
@@ -79,6 +80,8 @@ if (args.includes("--install-cep") || args.includes("--diagnose-cep")) {
|
|
|
79
80
|
process.exit(0);
|
|
80
81
|
}
|
|
81
82
|
async function main() {
|
|
83
|
+
process.env.PREMIERE_MCP_TRANSPORT = "stdio";
|
|
84
|
+
const telemetry = getTelemetry();
|
|
82
85
|
const bridgeOptions = {
|
|
83
86
|
tempDir: process.env.PREMIERE_TEMP_DIR,
|
|
84
87
|
timeoutMs: process.env.PREMIERE_TIMEOUT_MS
|
|
@@ -102,7 +105,7 @@ async function main() {
|
|
|
102
105
|
const address = uxpBridge.address();
|
|
103
106
|
debugLog(`UXP bridge listening on ws://${address.host}:${address.port}${address.path}`);
|
|
104
107
|
}
|
|
105
|
-
const server = createServer(bridgeOptions, { uxpBridge });
|
|
108
|
+
const server = createServer(bridgeOptions, { uxpBridge, telemetry });
|
|
106
109
|
const transport = new StdioServerTransport();
|
|
107
110
|
await server.connect(transport);
|
|
108
111
|
debugLog("Server connected and ready");
|
|
@@ -110,6 +113,7 @@ async function main() {
|
|
|
110
113
|
if (uxpBridge)
|
|
111
114
|
await uxpBridge.stop();
|
|
112
115
|
await server.close();
|
|
116
|
+
await telemetry.shutdown();
|
|
113
117
|
};
|
|
114
118
|
process.once("SIGINT", () => void shutdown().finally(() => process.exit(0)));
|
|
115
119
|
process.once("SIGTERM", () => void shutdown().finally(() => process.exit(0)));
|
|
@@ -19,5 +19,20 @@ export declare function requireCapability(config: CapabilityConfig, capability:
|
|
|
19
19
|
export declare const UNSAFE_TOOL_NAMES: Set<string>;
|
|
20
20
|
/** A conservative classification for centralized server registration. */
|
|
21
21
|
export declare function capabilityForTool(toolName: string): Capability;
|
|
22
|
+
/**
|
|
23
|
+
* Tools that stay advertised under every profile, because they are how an
|
|
24
|
+
* operator diagnoses a profile that is too narrow: get_capabilities reports the
|
|
25
|
+
* active authority, and ping proves the bridge is alive. Withholding them makes
|
|
26
|
+
* a misconfigured server look broken with no supported way to ask why.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ALWAYS_LISTED_TOOL_NAMES: Set<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a tool should appear in tools/list under the given profile.
|
|
31
|
+
*
|
|
32
|
+
* This is an advertising decision, not an enforcement one — guardToolHandler
|
|
33
|
+
* remains the authority check at call time. Keeping the two separate means a
|
|
34
|
+
* listing bug can never widen what a profile is actually allowed to do.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isToolPermitted(toolName: string, config: CapabilityConfig): boolean;
|
|
22
37
|
export declare function guardToolHandler<TArgs, TResult>(toolName: string, handler: (args: TArgs) => Promise<TResult>, config?: CapabilityConfig, createOperationId?: () => string): (args: TArgs) => Promise<TResult>;
|
|
23
38
|
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -39,7 +39,10 @@ export function requireCapability(config, capability, operationId) {
|
|
|
39
39
|
}
|
|
40
40
|
export const UNSAFE_TOOL_NAMES = new Set(["execute_extendscript", "send_raw_script", "evaluate_expression"]);
|
|
41
41
|
const INSPECT_TOOL_NAMES = new Set(["ping", "get_capabilities", "preview_edit_plan"]);
|
|
42
|
-
|
|
42
|
+
// detect_silence reads a media file from disk and shells out to ffmpeg. It
|
|
43
|
+
// changes nothing in Premiere, so classifying it as "edit" would overstate what
|
|
44
|
+
// it does; filesystem is the authority it actually needs.
|
|
45
|
+
const FILESYSTEM_TOOL_NAMES = new Set(["apply_lut", "set_scratch_disk_path", "verify_delivery_file", "detect_silence"]);
|
|
43
46
|
/** A conservative classification for centralized server registration. */
|
|
44
47
|
export function capabilityForTool(toolName) {
|
|
45
48
|
if (UNSAFE_TOOL_NAMES.has(toolName))
|
|
@@ -56,6 +59,25 @@ export function capabilityForTool(toolName) {
|
|
|
56
59
|
// keeps new tools fail-closed instead of silently bypassing the authority profile.
|
|
57
60
|
return "edit";
|
|
58
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Tools that stay advertised under every profile, because they are how an
|
|
64
|
+
* operator diagnoses a profile that is too narrow: get_capabilities reports the
|
|
65
|
+
* active authority, and ping proves the bridge is alive. Withholding them makes
|
|
66
|
+
* a misconfigured server look broken with no supported way to ask why.
|
|
67
|
+
*/
|
|
68
|
+
export const ALWAYS_LISTED_TOOL_NAMES = new Set(["ping", "get_capabilities"]);
|
|
69
|
+
/**
|
|
70
|
+
* Whether a tool should appear in tools/list under the given profile.
|
|
71
|
+
*
|
|
72
|
+
* This is an advertising decision, not an enforcement one — guardToolHandler
|
|
73
|
+
* remains the authority check at call time. Keeping the two separate means a
|
|
74
|
+
* listing bug can never widen what a profile is actually allowed to do.
|
|
75
|
+
*/
|
|
76
|
+
export function isToolPermitted(toolName, config) {
|
|
77
|
+
if (ALWAYS_LISTED_TOOL_NAMES.has(toolName))
|
|
78
|
+
return true;
|
|
79
|
+
return config.capabilities.has(capabilityForTool(toolName));
|
|
80
|
+
}
|
|
59
81
|
export function guardToolHandler(toolName, handler, config = resolveCapabilities(), createOperationId = randomUUID) {
|
|
60
82
|
const required = capabilityForTool(toolName);
|
|
61
83
|
return async (args) => {
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { BridgeOptions } from "./bridge/file-bridge.js";
|
|
3
3
|
import type { UxpWebSocketBridge } from "./bridge/uxp-websocket-bridge.js";
|
|
4
|
+
import { type Telemetry } from "./telemetry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Read the version from package.json rather than hardcoding it. A literal here
|
|
7
|
+
* silently drifts from the published package every release, which makes the
|
|
8
|
+
* version reported over MCP useless for triaging bug reports.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SERVER_VERSION: string;
|
|
4
11
|
export interface ServerOptions {
|
|
5
12
|
uxpBridge?: UxpWebSocketBridge;
|
|
13
|
+
telemetry?: Telemetry;
|
|
6
14
|
}
|
|
7
15
|
export declare function createServer(bridgeOptions: BridgeOptions, serverOptions?: ServerOptions): McpServer;
|
|
8
16
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.js
CHANGED
|
@@ -31,11 +31,31 @@ import { getEditPlanTools } from "./tools/edit-plans.js";
|
|
|
31
31
|
import { getAvSettingsTools } from "./tools/av-settings.js";
|
|
32
32
|
import { getRecoveryTools } from "./tools/recovery.js";
|
|
33
33
|
import { getUxpTools } from "./tools/uxp.js";
|
|
34
|
-
import { guardToolHandler, resolveCapabilities } from "./security/index.js";
|
|
34
|
+
import { guardToolHandler, isToolPermitted, resolveCapabilities, } from "./security/index.js";
|
|
35
35
|
import { EXTENDSCRIPT_REFERENCE } from "./resources/extendscript-reference.js";
|
|
36
36
|
import { WORKFLOW_PROMPTS, WORKFLOW_RESOURCE } from "./workflows/catalog.js";
|
|
37
37
|
import { annotationsForTool, structuredToolResult, } from "./workflows/tool-metadata.js";
|
|
38
|
+
import { getTelemetry } from "./telemetry.js";
|
|
38
39
|
import { z } from "zod";
|
|
40
|
+
import { readFileSync } from "node:fs";
|
|
41
|
+
import { fileURLToPath } from "node:url";
|
|
42
|
+
import path from "node:path";
|
|
43
|
+
/**
|
|
44
|
+
* Read the version from package.json rather than hardcoding it. A literal here
|
|
45
|
+
* silently drifts from the published package every release, which makes the
|
|
46
|
+
* version reported over MCP useless for triaging bug reports.
|
|
47
|
+
*/
|
|
48
|
+
export const SERVER_VERSION = (() => {
|
|
49
|
+
try {
|
|
50
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
51
|
+
const raw = readFileSync(path.resolve(here, "../package.json"), "utf8");
|
|
52
|
+
const version = JSON.parse(raw).version;
|
|
53
|
+
return typeof version === "string" && version ? version : "unknown";
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return "unknown";
|
|
57
|
+
}
|
|
58
|
+
})();
|
|
39
59
|
const PREMIERE_INSTRUCTIONS = `You are controlling Adobe Premiere Pro through MCP tools. Follow these best practices:
|
|
40
60
|
|
|
41
61
|
WORKFLOW ORDER:
|
|
@@ -222,18 +242,34 @@ function collectTools(bridgeOptions, capabilities, uxpBridge) {
|
|
|
222
242
|
export function createServer(bridgeOptions, serverOptions = {}) {
|
|
223
243
|
const server = new McpServer({
|
|
224
244
|
name: "premiere-pro-mcp",
|
|
225
|
-
version:
|
|
245
|
+
version: SERVER_VERSION,
|
|
226
246
|
});
|
|
227
247
|
const capabilities = resolveCapabilities();
|
|
248
|
+
const telemetry = serverOptions.telemetry ?? getTelemetry();
|
|
228
249
|
// Collect all tools from each module
|
|
229
250
|
const toolModules = collectTools(bridgeOptions, capabilities, serverOptions.uxpBridge);
|
|
230
251
|
// Register each tool with the MCP server
|
|
252
|
+
let withheld = 0;
|
|
231
253
|
for (const [name, tool] of Object.entries(toolModules)) {
|
|
254
|
+
// Don't advertise tools the active authority profile will always refuse.
|
|
255
|
+
// guardToolHandler still rejects them at call time, but listing an
|
|
256
|
+
// unusable tool spends client context and invites the model to attempt a
|
|
257
|
+
// call that cannot succeed.
|
|
258
|
+
if (!isToolPermitted(name, capabilities)) {
|
|
259
|
+
withheld++;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
232
262
|
const zodShape = jsonSchemaToZodShape(tool.parameters);
|
|
233
263
|
const guardedHandler = guardToolHandler(name, tool.handler, capabilities);
|
|
234
264
|
server.tool(name, tool.description, zodShape, annotationsForTool(name), async (args) => {
|
|
265
|
+
const startedAt = Date.now();
|
|
235
266
|
try {
|
|
236
267
|
const result = await guardedHandler(args);
|
|
268
|
+
telemetry.capture("mcp_tool_call", {
|
|
269
|
+
tool: name,
|
|
270
|
+
outcome: result.success ? "succeeded" : "failed",
|
|
271
|
+
duration_ms: Date.now() - startedAt,
|
|
272
|
+
});
|
|
237
273
|
if (result.success) {
|
|
238
274
|
// Special handling for capture_frame: return image content block
|
|
239
275
|
const data = result.data;
|
|
@@ -281,6 +317,12 @@ export function createServer(bridgeOptions, serverOptions = {}) {
|
|
|
281
317
|
}
|
|
282
318
|
}
|
|
283
319
|
catch (err) {
|
|
320
|
+
telemetry.capture("mcp_tool_call", {
|
|
321
|
+
tool: name,
|
|
322
|
+
outcome: "failed",
|
|
323
|
+
duration_ms: Date.now() - startedAt,
|
|
324
|
+
error_type: err instanceof Error ? err.name : "UnknownError",
|
|
325
|
+
});
|
|
284
326
|
return {
|
|
285
327
|
structuredContent: structuredToolResult(name, false, undefined, err instanceof Error ? err.message : String(err)),
|
|
286
328
|
content: [
|
|
@@ -294,6 +336,11 @@ export function createServer(bridgeOptions, serverOptions = {}) {
|
|
|
294
336
|
}
|
|
295
337
|
});
|
|
296
338
|
}
|
|
339
|
+
if (withheld > 0) {
|
|
340
|
+
debugLog(`Withheld ${withheld} tool(s) from tools/list — not permitted by the ` +
|
|
341
|
+
`active capability profile (${[...capabilities.capabilities].sort().join(", ")}). ` +
|
|
342
|
+
`Call get_capabilities to see the enabled authority.`);
|
|
343
|
+
}
|
|
297
344
|
// Register LLM instructions resource
|
|
298
345
|
server.resource("premiere-instructions", "config://premiere-instructions", {
|
|
299
346
|
description: "Instructions and best practices for using Premiere Pro via MCP tools",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type TelemetryProperties = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
export interface Telemetry {
|
|
3
|
+
readonly enabled: boolean;
|
|
4
|
+
capture(event: string, properties?: TelemetryProperties): void;
|
|
5
|
+
shutdown(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export declare function getTelemetry(): Telemetry;
|
|
8
|
+
//# sourceMappingURL=telemetry.d.ts.map
|