premiere-pro-mcp 1.2.3 → 1.3.1
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 +31 -0
- package/README.md +72 -43
- package/artifacts/MCPBridgeCEP.zxp +0 -0
- package/cep-plugin/CSXS/manifest.xml +3 -3
- package/dist/index.js +26 -11
- package/dist/platform-capabilities.d.ts +3 -3
- package/dist/server.js +71 -33
- package/dist/tools/advanced.d.ts +3 -0
- package/dist/tools/advanced.js +11 -2
- package/dist/tools/edit-plans.d.ts +3 -3
- package/dist/tools/health.d.ts +3 -3
- package/dist/tools/project.d.ts +6 -0
- package/dist/tools/project.js +9 -3
- package/dist/tools/track-targeting.d.ts +3 -0
- package/dist/tools/track-targeting.js +14 -7
- package/dist/tools/utility.d.ts +5 -0
- package/dist/tools/utility.js +59 -14
- package/dist/workflows/catalog.d.ts +2 -2
- package/dist/workflows/tool-metadata.d.ts +2 -2
- package/package.json +12 -7
- package/scripts/build-chat-dmg.sh +2 -2
- package/scripts/build-chat-zip.sh +2 -2
- package/scripts/build-signed-cep.ps1 +66 -0
- package/scripts/install-cep.ps1 +33 -2
- package/uxp-plugin/manifest.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.3.1] - 2026-07-25
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed `set_sequence_frame_rate` to convert frames per second into Premiere's required
|
|
14
|
+
ticks-per-frame `Time` value and verify the applied setting instead of assigning a numeric frame
|
|
15
|
+
period that could corrupt the sequence timebase. ([#37](https://github.com/leancoderkavy/premiere-pro-mcp/issues/37))
|
|
16
|
+
|
|
17
|
+
## [1.3.0] - 2026-07-25
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Added a Windows release workflow that builds and verifies a signed CEP ZXP with Adobe's pinned
|
|
22
|
+
`ZXPSignCmd`, includes it in the npm package, and installs it ahead of the unsigned development
|
|
23
|
+
bundle.
|
|
24
|
+
- Added `--diagnose-cep` to verify installation metadata, debug-key types, and recent Premiere
|
|
25
|
+
signature failures.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Upgraded the toolchain to TypeScript 7, Vitest 4, Zod 4, `@types/node` 26, and
|
|
30
|
+
`@modelcontextprotocol/sdk` 1.29.
|
|
31
|
+
- Updated the landing app to Next.js 16.2.12 and patched production transitive dependencies.
|
|
32
|
+
- Raised the supported Node.js floor to 20.19 and expanded CI through Node.js 24.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Added explicit Node types for TypeScript 7 and updated Zod 4 JSON-schema conversion.
|
|
37
|
+
- Fixed Windows installations that require a signed CEP extension instead of the debug-mode raw
|
|
38
|
+
folder used by development builds. ([#36](https://github.com/leancoderkavy/premiere-pro-mcp/issues/36))
|
|
39
|
+
|
|
9
40
|
## [1.2.3] - 2026-07-23
|
|
10
41
|
|
|
11
42
|
### Changed
|
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
269 tools across 29 modules, 3 resources, and 4 guided workflows.
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
|
-
[](https://nodejs.org)
|
|
11
|
+
[](https://modelcontextprotocol.io)
|
|
12
12
|
[](https://www.npmjs.com/package/premiere-pro-mcp)
|
|
13
13
|
[](https://premiere-pro-mcp.fly.dev)
|
|
14
14
|
[](https://www.adobe.com/products/premiere.html)
|
|
@@ -19,23 +19,24 @@
|
|
|
19
19
|
|
|
20
20
|
## What is this?
|
|
21
21
|
|
|
22
|
-
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that lets AI assistants like **Claude**, **Windsurf**, **Cursor**, or any MCP-compatible client directly control Adobe Premiere Pro — importing media, editing timelines, applying effects, managing keyframes, exporting, and more.
|
|
22
|
+
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that lets AI assistants like **Claude**, **Windsurf**, **Cursor**, **GitHub Copilot**, or any MCP-compatible client directly control Adobe Premiere Pro — importing media, editing timelines, applying effects, managing keyframes, exporting, and more.
|
|
23
23
|
|
|
24
|
-
```
|
|
24
|
+
```text
|
|
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
28
|
The AI handles the entire workflow through 269 tools spanning the supported ExtendScript, QE DOM, and safe edit-planning surfaces.
|
|
29
29
|
|
|
30
|
-
### What's new in 1.
|
|
30
|
+
### What's new in 1.3.1
|
|
31
31
|
|
|
32
|
-
- npm
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
- Windows npm releases now include a verified, signed CEP ZXP and install it automatically, covering
|
|
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.
|
|
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.
|
|
39
40
|
|
|
40
41
|
### Added in 1.2.0
|
|
41
42
|
|
|
@@ -189,6 +190,24 @@ Add to `.cursor/mcp.json` in your project or global config:
|
|
|
189
190
|
|
|
190
191
|
</details>
|
|
191
192
|
|
|
193
|
+
<details>
|
|
194
|
+
<summary><strong>GitHub Copilot (VS Code)</strong></summary>
|
|
195
|
+
|
|
196
|
+
Add to your VS Code MCP server configuration:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"mcpServers": {
|
|
201
|
+
"premiere-pro": {
|
|
202
|
+
"command": "node",
|
|
203
|
+
"args": ["/absolute/path/to/premiere-pro-mcp/dist/index.js"]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
</details>
|
|
210
|
+
|
|
192
211
|
### 4. Verify the bridge in Premiere Pro
|
|
193
212
|
|
|
194
213
|
1. Open (or restart) Premiere Pro
|
|
@@ -201,7 +220,7 @@ The default bridge directory is derived from the operating system on both sides,
|
|
|
201
220
|
### Windows and macOS capability coverage
|
|
202
221
|
|
|
203
222
|
| Surface | Windows | macOS | Verification boundary |
|
|
204
|
-
|
|
223
|
+
| :------ | :------ | :---- | :-------------------- |
|
|
205
224
|
| CEP production bridge | Premiere Pro 2020–2026 | Premiere Pro 2020–2026 | Run `get_capabilities`, then `ping` with Premiere open |
|
|
206
225
|
| UXP preview bridge | Premiere Pro 25.6+ | Premiere Pro 25.6+ | Live loopback WebSocket and host API verification required |
|
|
207
226
|
| npm CEP installer | Copies plugin and verifies `REG_SZ` debug keys | Copies plugin and verifies the installed manifest/debug settings | Restart Premiere after installation |
|
|
@@ -214,28 +233,31 @@ The default bridge directory is derived from the operating system on both sides,
|
|
|
214
233
|
## Architecture
|
|
215
234
|
|
|
216
235
|
**Local (stdio):**
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
236
|
+
|
|
237
|
+
```text
|
|
238
|
+
┌───────────────┐ stdio (MCP) ┌──────────────┐ File-based IPC ┌───────────────┐
|
|
239
|
+
│ AI Client │ ◄──────────────► │ MCP Server │ ◄────────────────► │ CEP Plugin │
|
|
220
240
|
│ (Claude, │ │ (Node.js / │ .jsx commands │ (runs inside │
|
|
221
|
-
│ Windsurf, │ │
|
|
222
|
-
│ Cursor
|
|
241
|
+
│ Windsurf, │ │ TypeScript) │ .json responses │ Premiere) │
|
|
242
|
+
│ Cursor, │ └──────────────┘ └──────┬────────┘
|
|
243
|
+
│ Copilot) │ │
|
|
223
244
|
└───────────────┘ │ evalScript()
|
|
224
245
|
▼
|
|
225
|
-
|
|
246
|
+
┌───────────────┐
|
|
226
247
|
│ Premiere Pro │
|
|
227
248
|
│ ExtendScript │
|
|
228
249
|
│ + QE DOM │
|
|
229
|
-
|
|
250
|
+
└───────────────┘
|
|
230
251
|
```
|
|
231
252
|
|
|
232
253
|
**Remote (HTTP/SSE — Fly.io):**
|
|
233
|
-
|
|
254
|
+
|
|
255
|
+
```text
|
|
234
256
|
┌───────────────┐ HTTP+SSE (MCP) ┌─────────────────────┐ File-based IPC ┌──────────────┐
|
|
235
|
-
│ AI Client │
|
|
236
|
-
│ (any MCP │
|
|
237
|
-
│ client) │
|
|
238
|
-
└───────────────┘
|
|
257
|
+
│ AI Client │ ◄──────────────► │ MCP Server │ ◄────────────────► │ CEP Plugin │
|
|
258
|
+
│ (any MCP │ │ premiere-pro-mcp │ .jsx / .json │ (Premiere) │
|
|
259
|
+
│ client) │ │ .fly.dev │ shared volume └──────────────┘
|
|
260
|
+
└───────────────┘ └─────────────────────┘
|
|
239
261
|
```
|
|
240
262
|
|
|
241
263
|
1. AI client invokes an MCP tool (e.g., `add_to_timeline`)
|
|
@@ -248,12 +270,12 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
248
270
|
|
|
249
271
|
---
|
|
250
272
|
|
|
251
|
-
## Tools (
|
|
273
|
+
## Tools (269)
|
|
252
274
|
|
|
253
275
|
### Discovery & Inspection (10 + 10)
|
|
254
276
|
|
|
255
277
|
| Tool | Description |
|
|
256
|
-
|
|
278
|
+
| :--- | :---------- |
|
|
257
279
|
| `get_project_info` | Current project name, path, sequences, items |
|
|
258
280
|
| `get_active_sequence` | Detailed active sequence with all clips |
|
|
259
281
|
| `list_project_items` | All items in the project panel |
|
|
@@ -268,7 +290,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
268
290
|
### Project Management (26)
|
|
269
291
|
|
|
270
292
|
| Tool | Description |
|
|
271
|
-
|
|
293
|
+
| :--- | :---------- |
|
|
272
294
|
| `save_project` / `save_project_as` / `open_project` | File operations |
|
|
273
295
|
| `create_project` / `close_project` | Project lifecycle |
|
|
274
296
|
| `import_media` / `import_folder` / `import_ae_comps` | Import media and AE comps |
|
|
@@ -281,7 +303,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
281
303
|
### Timeline & Editing (10 + 27 advanced)
|
|
282
304
|
|
|
283
305
|
| Tool | Description |
|
|
284
|
-
|
|
306
|
+
| :--- | :---------- |
|
|
285
307
|
| `add_to_timeline` / `overwrite_clip` | Insert and overwrite edits |
|
|
286
308
|
| `ripple_delete` | Remove clip and close gap (QE) |
|
|
287
309
|
| `roll_edit` / `slide_edit` / `slip_edit` | Professional trim modes (QE) |
|
|
@@ -302,7 +324,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
302
324
|
### Effects & Color (8)
|
|
303
325
|
|
|
304
326
|
| Tool | Description |
|
|
305
|
-
|
|
327
|
+
| :--- | :---------- |
|
|
306
328
|
| `apply_effect` / `apply_audio_effect` | Apply by name (QE) |
|
|
307
329
|
| `remove_effect` / `remove_all_effects` | Remove effects |
|
|
308
330
|
| `color_correct` | Lumetri: exposure, contrast, temperature, etc. |
|
|
@@ -312,7 +334,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
312
334
|
### Keyframes (8)
|
|
313
335
|
|
|
314
336
|
| Tool | Description |
|
|
315
|
-
|
|
337
|
+
| :--- | :---------- |
|
|
316
338
|
| `add_keyframe` / `get_keyframes` | Create and read keyframes |
|
|
317
339
|
| `remove_keyframe` / `remove_keyframe_range` | Delete keyframes |
|
|
318
340
|
| `set_keyframe_interpolation` | Linear / Hold / Bezier |
|
|
@@ -322,7 +344,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
322
344
|
### Export & Encoding (14)
|
|
323
345
|
|
|
324
346
|
| Tool | Description |
|
|
325
|
-
|
|
347
|
+
| :--- | :---------- |
|
|
326
348
|
| `export_sequence` | Export via Adobe Media Encoder |
|
|
327
349
|
| `capture_frame` | Export frame as PNG, return as base64 image |
|
|
328
350
|
| `export_as_fcp_xml` / `export_aaf` / `export_omf` | Interchange formats |
|
|
@@ -332,7 +354,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
332
354
|
### Source Monitor & Playback (7 + 4)
|
|
333
355
|
|
|
334
356
|
| Tool | Description |
|
|
335
|
-
|
|
357
|
+
| :--- | :---------- |
|
|
336
358
|
| `open_in_source` / `close_source_monitor` | Source monitor control |
|
|
337
359
|
| `insert_from_source` / `overwrite_from_source` | 3-point editing |
|
|
338
360
|
| `play_timeline` / `stop_playback` | Playback control (QE) |
|
|
@@ -341,7 +363,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
341
363
|
### Selection & Clipboard (7 + 6)
|
|
342
364
|
|
|
343
365
|
| Tool | Description |
|
|
344
|
-
|
|
366
|
+
| :--- | :---------- |
|
|
345
367
|
| `select_clips_by_name` / `select_clips_in_range` | Smart selection |
|
|
346
368
|
| `copy_effects_between_clips` | Copy effects via QE |
|
|
347
369
|
| `batch_apply_effect` | Apply effect to multiple clips |
|
|
@@ -350,7 +372,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
350
372
|
### Media Properties (16)
|
|
351
373
|
|
|
352
374
|
| Tool | Description |
|
|
353
|
-
|
|
375
|
+
| :--- | :---------- |
|
|
354
376
|
| `set_offline` / `has_proxy` / `detach_proxy` | Offline/proxy management |
|
|
355
377
|
| `set_override_frame_rate` | Override FPS |
|
|
356
378
|
| `set_scale_to_frame_size` | Auto-scale to sequence frame |
|
|
@@ -360,7 +382,7 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
360
382
|
### Sequence Management (11)
|
|
361
383
|
|
|
362
384
|
| Tool | Description |
|
|
363
|
-
|
|
385
|
+
| :--- | :---------- |
|
|
364
386
|
| `create_sequence` / `create_sequence_from_preset` | Create sequences from `.sqpreset` files without opening Premiere's modal dialog |
|
|
365
387
|
| `duplicate_sequence` / `delete_sequence` | Manage sequences |
|
|
366
388
|
| `auto_reframe_sequence` | Auto-reframe for social media |
|
|
@@ -370,14 +392,14 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
370
392
|
### Workspace & Captions (2 + 1)
|
|
371
393
|
|
|
372
394
|
| Tool | Description |
|
|
373
|
-
|
|
395
|
+
| :--- | :---------- |
|
|
374
396
|
| `get_workspaces` / `set_workspace` | Switch workspace layouts |
|
|
375
397
|
| `create_caption_track` | Create caption/subtitle tracks |
|
|
376
398
|
|
|
377
399
|
### Scripting (6)
|
|
378
400
|
|
|
379
401
|
| Tool | Description |
|
|
380
|
-
|
|
402
|
+
| :--- | :----------- |
|
|
381
403
|
| `execute_extendscript` | Run arbitrary ExtendScript (ES3) |
|
|
382
404
|
| `evaluate_expression` | Quick one-line eval |
|
|
383
405
|
| `send_raw_script` | Bypass security validation (advanced) |
|
|
@@ -393,7 +415,7 @@ Track targeting, batch operations, markers, audio levels, motion/transform, meta
|
|
|
393
415
|
The server exposes three LLM context resources and four workflow prompts:
|
|
394
416
|
|
|
395
417
|
| Resource URI | Description |
|
|
396
|
-
|
|
418
|
+
| :----------- | :---------- |
|
|
397
419
|
| `config://premiere-instructions` | Best practices: workflow order, timeline rules, effect tips, error handling |
|
|
398
420
|
| `config://extendscript-reference` | Complete ExtendScript API reference for writing custom scripts |
|
|
399
421
|
| `config://premiere-workflows` | Machine-readable catalog for rough cuts, dialogue cleanup, captions, and delivery |
|
|
@@ -434,6 +456,7 @@ fly deploy --remote-only
|
|
|
434
456
|
```
|
|
435
457
|
|
|
436
458
|
Then connect with:
|
|
459
|
+
|
|
437
460
|
```json
|
|
438
461
|
{
|
|
439
462
|
"mcpServers": {
|
|
@@ -453,11 +476,12 @@ Then connect with:
|
|
|
453
476
|
## Environment Variables
|
|
454
477
|
|
|
455
478
|
| Variable | Description | Default |
|
|
456
|
-
|
|
479
|
+
| :------- | :---------- | :------ |
|
|
457
480
|
| `PREMIERE_TEMP_DIR` | Shared temp directory for MCP ↔ CEP communication | OS temp dir + `/premiere-mcp-bridge` |
|
|
458
481
|
| `PREMIERE_TIMEOUT_MS` | Command timeout in milliseconds | `30000` |
|
|
459
482
|
| `PREMIERE_DEFAULT_SEQUENCE_PRESET` | Override the auto-discovered `.sqpreset` used by `create_sequence` | auto-discovered |
|
|
460
483
|
| `PREMIERE_MCP_CAPABILITIES` | Comma-separated authority profile; add `unsafe-script` only when raw scripting is required | `inspect,edit,export,filesystem` |
|
|
484
|
+
| `PREMIERE_MCP_DEBUG` | Set to `1` (or `true`) to emit verbose server diagnostics to stderr | unset |
|
|
461
485
|
| `PORT` | HTTP port (HTTP/SSE transport only) | `3000` |
|
|
462
486
|
| `MCP_AUTH_TOKEN` | Bearer token required by the HTTP transport | unset |
|
|
463
487
|
| `ALLOW_UNAUTHENTICATED` | Set to `1` to run HTTP without auth (unsafe; throwaway instances only) | unset |
|
|
@@ -466,16 +490,16 @@ Then connect with:
|
|
|
466
490
|
|
|
467
491
|
## Project Structure
|
|
468
492
|
|
|
469
|
-
```
|
|
493
|
+
```text
|
|
470
494
|
premiere-pro-mcp/
|
|
471
495
|
├── src/
|
|
472
496
|
│ ├── index.ts # Entry point — stdio transport setup
|
|
473
497
|
│ ├── http-server.ts # Entry point — HTTP/SSE transport (Fly.io / remote)
|
|
474
|
-
│ ├── server.ts # MCP server — registers
|
|
498
|
+
│ ├── server.ts # MCP server — registers 269 tools + 3 resources + 4 prompts
|
|
475
499
|
│ ├── bridge/
|
|
476
500
|
│ │ ├── file-bridge.ts # File-based IPC (write .jsx, poll .json)
|
|
477
501
|
│ │ └── script-builder.ts # ExtendScript generator with ES3 helpers
|
|
478
|
-
│ ├── tools/ #
|
|
502
|
+
│ ├── tools/ # 29 tool modules
|
|
479
503
|
│ │ ├── discovery.ts # Project discovery and queries
|
|
480
504
|
│ │ ├── project.ts # Project management and import
|
|
481
505
|
│ │ ├── media.ts # Media and proxy management
|
|
@@ -579,6 +603,11 @@ Many tools use the undocumented QE DOM (enabled via `app.enableQE()`). These too
|
|
|
579
603
|
- Windows: `dir "%APPDATA%\Adobe\CEP\extensions\MCPBridgeCEP"`
|
|
580
604
|
3. Completely restart Premiere Pro (not just close/reopen the project)
|
|
581
605
|
4. Check the CSXS version matches your Premiere Pro version
|
|
606
|
+
5. Run `premiere-pro-mcp --diagnose-cep` to check installation metadata and recent Premiere logs.
|
|
607
|
+
|
|
608
|
+
Version 1.3.0 and newer installs the signed `artifacts/MCPBridgeCEP.zxp` included in the npm
|
|
609
|
+
package on Windows. If diagnostics report `Signature verification failed`, reinstall the latest
|
|
610
|
+
npm version, fully quit every Premiere process, run `premiere-pro-mcp --install-cep`, and relaunch.
|
|
582
611
|
|
|
583
612
|
</details>
|
|
584
613
|
|
|
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.3.1" 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.3.1"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.3.1"/>
|
|
6
6
|
</ExtensionList>
|
|
7
7
|
<ExecutionEnvironment>
|
|
8
8
|
<HostList>
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,12 @@ import path from "path";
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
const projectRoot = path.resolve(__dirname, "..");
|
|
11
|
+
const debugEnabled = /^(1|true|yes|on|debug)$/i.test(process.env.PREMIERE_MCP_DEBUG ?? "");
|
|
12
|
+
function debugLog(message) {
|
|
13
|
+
if (debugEnabled) {
|
|
14
|
+
console.error(`[premiere-pro-mcp] ${message}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
11
17
|
// Handle CLI flags
|
|
12
18
|
const args = process.argv.slice(2);
|
|
13
19
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -17,6 +23,7 @@ premiere-pro-mcp — MCP server for Adobe Premiere Pro (269 tools)
|
|
|
17
23
|
Usage:
|
|
18
24
|
premiere-pro-mcp Start the MCP server (stdio transport)
|
|
19
25
|
premiere-pro-mcp --install-cep Install the CEP plugin into Premiere Pro
|
|
26
|
+
premiere-pro-mcp --diagnose-cep Check the CEP install, debug keys, and Premiere signature logs
|
|
20
27
|
premiere-pro-mcp --help Show this help message
|
|
21
28
|
premiere-pro-mcp --version Show version
|
|
22
29
|
|
|
@@ -24,8 +31,9 @@ Environment variables:
|
|
|
24
31
|
PREMIERE_TEMP_DIR Shared temp directory (default: OS temp + /premiere-mcp-bridge)
|
|
25
32
|
PREMIERE_TIMEOUT_MS Command timeout in ms (default: 30000)
|
|
26
33
|
PREMIERE_MCP_CAPABILITIES Comma-separated authority profile
|
|
34
|
+
PREMIERE_MCP_DEBUG Set to 1/true to enable verbose stderr diagnostics
|
|
27
35
|
|
|
28
|
-
More info: https://github.com/
|
|
36
|
+
More info: https://github.com/leancoderkavy/premiere-pro-mcp
|
|
29
37
|
`);
|
|
30
38
|
process.exit(0);
|
|
31
39
|
}
|
|
@@ -34,8 +42,9 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
34
42
|
console.log(pkg.default.version);
|
|
35
43
|
process.exit(0);
|
|
36
44
|
}
|
|
37
|
-
if (args.includes("--install-cep")) {
|
|
38
|
-
|
|
45
|
+
if (args.includes("--install-cep") || args.includes("--diagnose-cep")) {
|
|
46
|
+
const diagnose = args.includes("--diagnose-cep");
|
|
47
|
+
console.log(diagnose ? "Diagnosing CEP plugin...\n" : "Installing CEP plugin...\n");
|
|
39
48
|
const isWindows = process.platform === "win32";
|
|
40
49
|
const isMacOS = process.platform === "darwin";
|
|
41
50
|
if (!isWindows && !isMacOS) {
|
|
@@ -45,17 +54,23 @@ if (args.includes("--install-cep")) {
|
|
|
45
54
|
const scriptPath = path.join(projectRoot, "scripts", isWindows ? "install-cep.ps1" : "install-cep.sh");
|
|
46
55
|
try {
|
|
47
56
|
if (isWindows) {
|
|
48
|
-
|
|
57
|
+
const powershellArgs = ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", scriptPath];
|
|
58
|
+
if (diagnose)
|
|
59
|
+
powershellArgs.push("-Diagnose");
|
|
60
|
+
execFileSync("powershell.exe", powershellArgs, { stdio: "inherit", cwd: projectRoot });
|
|
49
61
|
}
|
|
50
62
|
else {
|
|
51
|
-
execFileSync("bash", [scriptPath, "--
|
|
63
|
+
execFileSync("bash", [scriptPath, diagnose ? "--diagnose" : "--copy"], {
|
|
64
|
+
stdio: "inherit",
|
|
65
|
+
cwd: projectRoot,
|
|
66
|
+
});
|
|
52
67
|
}
|
|
53
68
|
}
|
|
54
69
|
catch {
|
|
55
|
-
console.error(
|
|
70
|
+
console.error(`CEP ${diagnose ? "diagnostics" : "installation"} failed. Try running manually:`);
|
|
56
71
|
console.error(isWindows
|
|
57
|
-
? ` powershell -ExecutionPolicy Bypass -File "${scriptPath}"`
|
|
58
|
-
: ` bash "${scriptPath}"`);
|
|
72
|
+
? ` powershell -ExecutionPolicy Bypass -File "${scriptPath}"${diagnose ? " -Diagnose" : ""}`
|
|
73
|
+
: ` bash "${scriptPath}" ${diagnose ? "--diagnose" : "--copy"}`);
|
|
59
74
|
process.exit(1);
|
|
60
75
|
}
|
|
61
76
|
process.exit(0);
|
|
@@ -68,14 +83,14 @@ async function main() {
|
|
|
68
83
|
: undefined,
|
|
69
84
|
};
|
|
70
85
|
const tempDir = getTempDir(bridgeOptions);
|
|
71
|
-
|
|
72
|
-
|
|
86
|
+
debugLog("Starting MCP server...");
|
|
87
|
+
debugLog(`Temp directory: ${tempDir}`);
|
|
73
88
|
// Clean up any stale files from previous sessions
|
|
74
89
|
cleanupTempDir(bridgeOptions);
|
|
75
90
|
const server = createServer(bridgeOptions);
|
|
76
91
|
const transport = new StdioServerTransport();
|
|
77
92
|
await server.connect(transport);
|
|
78
|
-
|
|
93
|
+
debugLog("Server connected and ready");
|
|
79
94
|
}
|
|
80
95
|
main().catch((err) => {
|
|
81
96
|
console.error("[premiere-pro-mcp] Fatal error:", err);
|
|
@@ -22,7 +22,7 @@ export declare function buildPlatformCapabilityReport(capabilities: CapabilityCo
|
|
|
22
22
|
platforms: string[];
|
|
23
23
|
premiereVersions: string;
|
|
24
24
|
transport: string;
|
|
25
|
-
capabilities: ("
|
|
25
|
+
capabilities: ("edit" | "export" | "filesystem" | "inspect" | "unsafe-script")[];
|
|
26
26
|
};
|
|
27
27
|
uxp: {
|
|
28
28
|
status: string;
|
|
@@ -35,8 +35,8 @@ export declare function buildPlatformCapabilityReport(capabilities: CapabilityCo
|
|
|
35
35
|
};
|
|
36
36
|
authority: {
|
|
37
37
|
source: "default" | "environment" | "explicit";
|
|
38
|
-
enabled: ("
|
|
39
|
-
disabled: ("
|
|
38
|
+
enabled: ("edit" | "export" | "filesystem" | "inspect" | "unsafe-script")[];
|
|
39
|
+
disabled: ("edit" | "export" | "filesystem" | "inspect" | "unsafe-script")[];
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
42
|
//# sourceMappingURL=platform-capabilities.d.ts.map
|
package/dist/server.js
CHANGED
|
@@ -31,7 +31,7 @@ import { getEditPlanTools } from "./tools/edit-plans.js";
|
|
|
31
31
|
import { guardToolHandler, resolveCapabilities } from "./security/index.js";
|
|
32
32
|
import { EXTENDSCRIPT_REFERENCE } from "./resources/extendscript-reference.js";
|
|
33
33
|
import { WORKFLOW_PROMPTS, WORKFLOW_RESOURCE } from "./workflows/catalog.js";
|
|
34
|
-
import { annotationsForTool, structuredToolResult } from "./workflows/tool-metadata.js";
|
|
34
|
+
import { annotationsForTool, structuredToolResult, } from "./workflows/tool-metadata.js";
|
|
35
35
|
import { z } from "zod";
|
|
36
36
|
const PREMIERE_INSTRUCTIONS = `You are controlling Adobe Premiere Pro through MCP tools. Follow these best practices:
|
|
37
37
|
|
|
@@ -96,6 +96,56 @@ CUSTOM SCRIPTING:
|
|
|
96
96
|
`;
|
|
97
97
|
const toolCatalogCache = new Map();
|
|
98
98
|
const schemaCache = new WeakMap();
|
|
99
|
+
const debugEnabled = /^(1|true|yes|on|debug)$/i.test(process.env.PREMIERE_MCP_DEBUG ?? "");
|
|
100
|
+
function debugLog(message) {
|
|
101
|
+
if (debugEnabled) {
|
|
102
|
+
console.error(`[premiere-pro-mcp] ${message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function jsonSchemaPropToZod(prop) {
|
|
106
|
+
const propType = prop.type;
|
|
107
|
+
if (propType === "string") {
|
|
108
|
+
if (prop.enum && Array.isArray(prop.enum) && prop.enum.length > 0) {
|
|
109
|
+
const enumValues = prop.enum;
|
|
110
|
+
return z.enum(enumValues);
|
|
111
|
+
}
|
|
112
|
+
return z.string();
|
|
113
|
+
}
|
|
114
|
+
if (propType === "number") {
|
|
115
|
+
return z.number();
|
|
116
|
+
}
|
|
117
|
+
if (propType === "boolean") {
|
|
118
|
+
return z.boolean();
|
|
119
|
+
}
|
|
120
|
+
if (propType === "array") {
|
|
121
|
+
const itemSchema = (prop.items ?? {});
|
|
122
|
+
// Use unknown as a safe fallback while still emitting a concrete items schema.
|
|
123
|
+
const itemZod = Object.keys(itemSchema).length > 0
|
|
124
|
+
? jsonSchemaPropToZod(itemSchema)
|
|
125
|
+
: z.unknown();
|
|
126
|
+
return z.array(itemZod);
|
|
127
|
+
}
|
|
128
|
+
if (propType === "object") {
|
|
129
|
+
const nestedProperties = (prop.properties ?? {});
|
|
130
|
+
const nestedRequired = new Set((prop.required ?? []));
|
|
131
|
+
if (Object.keys(nestedProperties).length === 0) {
|
|
132
|
+
return z.record(z.string(), z.unknown());
|
|
133
|
+
}
|
|
134
|
+
const nestedShape = {};
|
|
135
|
+
for (const [nestedKey, nestedProp] of Object.entries(nestedProperties)) {
|
|
136
|
+
let nestedZod = jsonSchemaPropToZod(nestedProp);
|
|
137
|
+
if (nestedProp.description) {
|
|
138
|
+
nestedZod = nestedZod.describe(nestedProp.description);
|
|
139
|
+
}
|
|
140
|
+
if (!nestedRequired.has(nestedKey)) {
|
|
141
|
+
nestedZod = nestedZod.optional();
|
|
142
|
+
}
|
|
143
|
+
nestedShape[nestedKey] = nestedZod;
|
|
144
|
+
}
|
|
145
|
+
return z.object(nestedShape).passthrough();
|
|
146
|
+
}
|
|
147
|
+
return z.unknown();
|
|
148
|
+
}
|
|
99
149
|
/**
|
|
100
150
|
* Convert a JSON Schema-style parameters object to a Zod shape for MCP SDK registration.
|
|
101
151
|
*/
|
|
@@ -107,33 +157,7 @@ function jsonSchemaToZodShape(params) {
|
|
|
107
157
|
const properties = (params.properties ?? {});
|
|
108
158
|
const required = (params.required ?? []);
|
|
109
159
|
for (const [key, prop] of Object.entries(properties)) {
|
|
110
|
-
let zodType;
|
|
111
|
-
const propType = prop.type;
|
|
112
|
-
switch (propType) {
|
|
113
|
-
case "string":
|
|
114
|
-
if (prop.enum) {
|
|
115
|
-
const enumValues = prop.enum;
|
|
116
|
-
zodType = z.enum(enumValues);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
zodType = z.string();
|
|
120
|
-
}
|
|
121
|
-
break;
|
|
122
|
-
case "number":
|
|
123
|
-
zodType = z.number();
|
|
124
|
-
break;
|
|
125
|
-
case "boolean":
|
|
126
|
-
zodType = z.boolean();
|
|
127
|
-
break;
|
|
128
|
-
case "array":
|
|
129
|
-
zodType = z.array(z.any());
|
|
130
|
-
break;
|
|
131
|
-
case "object":
|
|
132
|
-
zodType = z.record(z.any());
|
|
133
|
-
break;
|
|
134
|
-
default:
|
|
135
|
-
zodType = z.any();
|
|
136
|
-
}
|
|
160
|
+
let zodType = jsonSchemaPropToZod(prop);
|
|
137
161
|
if (prop.description) {
|
|
138
162
|
zodType = zodType.describe(prop.description);
|
|
139
163
|
}
|
|
@@ -206,9 +230,13 @@ export function createServer(bridgeOptions) {
|
|
|
206
230
|
if (result.success) {
|
|
207
231
|
// Special handling for capture_frame: return image content block
|
|
208
232
|
const data = result.data;
|
|
209
|
-
if (data &&
|
|
233
|
+
if (data &&
|
|
234
|
+
data.mimeType === "image/png" &&
|
|
235
|
+
typeof data.base64 === "string") {
|
|
210
236
|
return {
|
|
211
|
-
structuredContent: structuredToolResult(name, true, {
|
|
237
|
+
structuredContent: structuredToolResult(name, true, {
|
|
238
|
+
mimeType: data.mimeType,
|
|
239
|
+
}),
|
|
212
240
|
content: [
|
|
213
241
|
{
|
|
214
242
|
type: "image",
|
|
@@ -275,10 +303,20 @@ export function createServer(bridgeOptions) {
|
|
|
275
303
|
description: "High-level, safety-oriented Premiere Pro workflow catalog",
|
|
276
304
|
mimeType: "application/json",
|
|
277
305
|
}, async (uri) => ({
|
|
278
|
-
contents: [
|
|
306
|
+
contents: [
|
|
307
|
+
{
|
|
308
|
+
uri: uri.href,
|
|
309
|
+
mimeType: "application/json",
|
|
310
|
+
text: WORKFLOW_RESOURCE,
|
|
311
|
+
},
|
|
312
|
+
],
|
|
279
313
|
}));
|
|
280
314
|
for (const prompt of WORKFLOW_PROMPTS) {
|
|
281
|
-
server.registerPrompt(prompt.name, {
|
|
315
|
+
server.registerPrompt(prompt.name, {
|
|
316
|
+
title: prompt.title,
|
|
317
|
+
description: prompt.description,
|
|
318
|
+
argsSchema: prompt.argsSchema,
|
|
319
|
+
}, prompt.render);
|
|
282
320
|
}
|
|
283
321
|
// Register ExtendScript API reference resource
|
|
284
322
|
server.resource("extendscript-reference", "config://extendscript-reference", {
|
|
@@ -293,7 +331,7 @@ export function createServer(bridgeOptions) {
|
|
|
293
331
|
],
|
|
294
332
|
}));
|
|
295
333
|
const toolCount = Object.keys(toolModules).length;
|
|
296
|
-
|
|
334
|
+
debugLog(`Registered ${toolCount} tools + 3 resources + ${WORKFLOW_PROMPTS.length} prompts`);
|
|
297
335
|
return server;
|
|
298
336
|
}
|
|
299
337
|
//# sourceMappingURL=server.js.map
|
package/dist/tools/advanced.d.ts
CHANGED
package/dist/tools/advanced.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildToolScript, escapeForExtendScript } from "../bridge/script-builder.js";
|
|
1
|
+
import { buildToolScript, escapeForExtendScript, } from "../bridge/script-builder.js";
|
|
2
2
|
import { sendCommand } from "../bridge/file-bridge.js";
|
|
3
3
|
export function getAdvancedTools(bridgeOptions) {
|
|
4
4
|
return {
|
|
@@ -573,6 +573,7 @@ export function getAdvancedTools(bridgeOptions) {
|
|
|
573
573
|
},
|
|
574
574
|
item_ids: {
|
|
575
575
|
type: "array",
|
|
576
|
+
items: { type: "string" },
|
|
576
577
|
description: "Array of project item names or node IDs to include in order",
|
|
577
578
|
},
|
|
578
579
|
},
|
|
@@ -792,7 +793,15 @@ export function getAdvancedTools(bridgeOptions) {
|
|
|
792
793
|
description: "Blue (0-255)",
|
|
793
794
|
},
|
|
794
795
|
},
|
|
795
|
-
required: [
|
|
796
|
+
required: [
|
|
797
|
+
"node_id",
|
|
798
|
+
"component_name",
|
|
799
|
+
"property_name",
|
|
800
|
+
"alpha",
|
|
801
|
+
"red",
|
|
802
|
+
"green",
|
|
803
|
+
"blue",
|
|
804
|
+
],
|
|
796
805
|
},
|
|
797
806
|
handler: async (args) => {
|
|
798
807
|
const script = buildToolScript(`
|
|
@@ -74,15 +74,15 @@ export declare function getEditPlanTools(bridgeOptions: BridgeOptions, dependenc
|
|
|
74
74
|
plan: unknown;
|
|
75
75
|
confirmation_token: string;
|
|
76
76
|
}) => Promise<{
|
|
77
|
+
success: boolean;
|
|
78
|
+
error?: string;
|
|
77
79
|
data: {
|
|
78
80
|
operationId: string;
|
|
79
81
|
};
|
|
80
|
-
success: boolean;
|
|
81
|
-
error?: string;
|
|
82
82
|
} | {
|
|
83
|
-
error: string;
|
|
84
83
|
success: boolean;
|
|
85
84
|
data?: unknown;
|
|
85
|
+
error: string;
|
|
86
86
|
}>;
|
|
87
87
|
};
|
|
88
88
|
};
|
package/dist/tools/health.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare function getHealthTools(bridgeOptions: BridgeOptions, capabilitie
|
|
|
26
26
|
platforms: string[];
|
|
27
27
|
premiereVersions: string;
|
|
28
28
|
transport: string;
|
|
29
|
-
capabilities: ("
|
|
29
|
+
capabilities: ("edit" | "export" | "filesystem" | "inspect" | "unsafe-script")[];
|
|
30
30
|
};
|
|
31
31
|
uxp: {
|
|
32
32
|
status: string;
|
|
@@ -39,8 +39,8 @@ export declare function getHealthTools(bridgeOptions: BridgeOptions, capabilitie
|
|
|
39
39
|
};
|
|
40
40
|
authority: {
|
|
41
41
|
source: "default" | "environment" | "explicit";
|
|
42
|
-
enabled: ("
|
|
43
|
-
disabled: ("
|
|
42
|
+
enabled: ("edit" | "export" | "filesystem" | "inspect" | "unsafe-script")[];
|
|
43
|
+
disabled: ("edit" | "export" | "filesystem" | "inspect" | "unsafe-script")[];
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
46
|
}>;
|
package/dist/tools/project.d.ts
CHANGED
|
@@ -115,6 +115,9 @@ export declare function getProjectTools(bridgeOptions: BridgeOptions): {
|
|
|
115
115
|
};
|
|
116
116
|
comp_names: {
|
|
117
117
|
type: string;
|
|
118
|
+
items: {
|
|
119
|
+
type: string;
|
|
120
|
+
};
|
|
118
121
|
description: string;
|
|
119
122
|
};
|
|
120
123
|
target_bin: {
|
|
@@ -246,6 +249,9 @@ export declare function getProjectTools(bridgeOptions: BridgeOptions): {
|
|
|
246
249
|
};
|
|
247
250
|
sequence_ids: {
|
|
248
251
|
type: string;
|
|
252
|
+
items: {
|
|
253
|
+
type: string;
|
|
254
|
+
};
|
|
249
255
|
description: string;
|
|
250
256
|
};
|
|
251
257
|
};
|
package/dist/tools/project.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildToolScript, escapeForExtendScript } from "../bridge/script-builder.js";
|
|
1
|
+
import { buildToolScript, escapeForExtendScript, } from "../bridge/script-builder.js";
|
|
2
2
|
import { sendCommand } from "../bridge/file-bridge.js";
|
|
3
3
|
export function getProjectTools(bridgeOptions) {
|
|
4
4
|
return {
|
|
@@ -169,6 +169,7 @@ export function getProjectTools(bridgeOptions) {
|
|
|
169
169
|
},
|
|
170
170
|
comp_names: {
|
|
171
171
|
type: "array",
|
|
172
|
+
items: { type: "string" },
|
|
172
173
|
description: "Array of composition names to import. If omitted, imports all comps.",
|
|
173
174
|
},
|
|
174
175
|
target_bin: {
|
|
@@ -183,7 +184,9 @@ export function getProjectTools(bridgeOptions) {
|
|
|
183
184
|
? `var targetBin = __findProjectItem("${escapeForExtendScript(args.target_bin)}"); if (!targetBin) return __error("Bin not found");`
|
|
184
185
|
: `var targetBin = app.project.rootItem;`;
|
|
185
186
|
if (args.comp_names && args.comp_names.length > 0) {
|
|
186
|
-
const comps = args.comp_names
|
|
187
|
+
const comps = args.comp_names
|
|
188
|
+
.map((c) => `"${escapeForExtendScript(c)}"`)
|
|
189
|
+
.join(", ");
|
|
187
190
|
const script = buildToolScript(`
|
|
188
191
|
${binLookup}
|
|
189
192
|
app.project.importAEComps("${escapeForExtendScript(args.ae_project_path)}", [${comps}], targetBin);
|
|
@@ -358,6 +361,7 @@ export function getProjectTools(bridgeOptions) {
|
|
|
358
361
|
},
|
|
359
362
|
sequence_ids: {
|
|
360
363
|
type: "array",
|
|
364
|
+
items: { type: "string" },
|
|
361
365
|
description: "Array of sequence IDs to import from the source project. If omitted, all sequences are imported.",
|
|
362
366
|
},
|
|
363
367
|
},
|
|
@@ -365,7 +369,9 @@ export function getProjectTools(bridgeOptions) {
|
|
|
365
369
|
},
|
|
366
370
|
handler: async (args) => {
|
|
367
371
|
if (args.sequence_ids && args.sequence_ids.length > 0) {
|
|
368
|
-
const ids = args.sequence_ids
|
|
372
|
+
const ids = args.sequence_ids
|
|
373
|
+
.map((id) => `"${escapeForExtendScript(id)}"`)
|
|
374
|
+
.join(", ");
|
|
369
375
|
const script = buildToolScript(`
|
|
370
376
|
app.project.importSequences("${escapeForExtendScript(args.project_path)}", [${ids}]);
|
|
371
377
|
return __result({ imported: true, sequenceIds: [${ids}] });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildToolScript, escapeForExtendScript } from "../bridge/script-builder.js";
|
|
1
|
+
import { buildToolScript, escapeForExtendScript, } from "../bridge/script-builder.js";
|
|
2
2
|
import { sendCommand } from "../bridge/file-bridge.js";
|
|
3
3
|
export function getTrackTargetingTools(bridgeOptions) {
|
|
4
4
|
return {
|
|
@@ -367,17 +367,21 @@ export function getTrackTargetingTools(bridgeOptions) {
|
|
|
367
367
|
var item = __findProjectItem("${escapeForExtendScript(args.item_id)}");
|
|
368
368
|
if (!item) return __error("Item not found");
|
|
369
369
|
|
|
370
|
-
${args.in_seconds !== undefined
|
|
370
|
+
${args.in_seconds !== undefined
|
|
371
|
+
? `
|
|
371
372
|
var inTime = new Time();
|
|
372
373
|
inTime.seconds = ${args.in_seconds};
|
|
373
374
|
item.setInPoint(inTime.ticks, ${mediaType});
|
|
374
|
-
`
|
|
375
|
+
`
|
|
376
|
+
: ""}
|
|
375
377
|
|
|
376
|
-
${args.out_seconds !== undefined
|
|
378
|
+
${args.out_seconds !== undefined
|
|
379
|
+
? `
|
|
377
380
|
var outTime = new Time();
|
|
378
381
|
outTime.seconds = ${args.out_seconds};
|
|
379
382
|
item.setOutPoint(outTime.ticks, ${mediaType});
|
|
380
|
-
`
|
|
383
|
+
`
|
|
384
|
+
: ""}
|
|
381
385
|
|
|
382
386
|
return __result({ item: item.name, inSet: ${args.in_seconds !== undefined}, outSet: ${args.out_seconds !== undefined} });
|
|
383
387
|
`);
|
|
@@ -403,10 +407,12 @@ export function getTrackTargetingTools(bridgeOptions) {
|
|
|
403
407
|
handler: async (args) => {
|
|
404
408
|
const script = buildToolScript(`
|
|
405
409
|
var targetBin = app.project.rootItem;
|
|
406
|
-
${args.target_bin
|
|
410
|
+
${args.target_bin
|
|
411
|
+
? `
|
|
407
412
|
var found = __findProjectItem("${escapeForExtendScript(args.target_bin)}");
|
|
408
413
|
if (found && found.type === 2) targetBin = found;
|
|
409
|
-
`
|
|
414
|
+
`
|
|
415
|
+
: ""}
|
|
410
416
|
|
|
411
417
|
app.project.importFiles(["${escapeForExtendScript(args.first_file_path)}"], true, targetBin, true);
|
|
412
418
|
|
|
@@ -1115,6 +1121,7 @@ export function getTrackTargetingTools(bridgeOptions) {
|
|
|
1115
1121
|
properties: {
|
|
1116
1122
|
item_ids: {
|
|
1117
1123
|
type: "array",
|
|
1124
|
+
items: { type: "string" },
|
|
1118
1125
|
description: "Array of node IDs or names of items to move",
|
|
1119
1126
|
},
|
|
1120
1127
|
target_bin: {
|
package/dist/tools/utility.d.ts
CHANGED
|
@@ -23,6 +23,9 @@ export declare function getUtilityTools(bridgeOptions: BridgeOptions): {
|
|
|
23
23
|
properties: {
|
|
24
24
|
item_ids: {
|
|
25
25
|
type: string;
|
|
26
|
+
items: {
|
|
27
|
+
type: string;
|
|
28
|
+
};
|
|
26
29
|
description: string;
|
|
27
30
|
};
|
|
28
31
|
};
|
|
@@ -101,6 +104,8 @@ export declare function getUtilityTools(bridgeOptions: BridgeOptions): {
|
|
|
101
104
|
properties: {
|
|
102
105
|
frame_rate: {
|
|
103
106
|
type: string;
|
|
107
|
+
minimum: number;
|
|
108
|
+
maximum: number;
|
|
104
109
|
description: string;
|
|
105
110
|
};
|
|
106
111
|
};
|
package/dist/tools/utility.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildToolScript, escapeForExtendScript } from "../bridge/script-builder.js";
|
|
1
|
+
import { buildToolScript, escapeForExtendScript, } from "../bridge/script-builder.js";
|
|
2
2
|
import { sendCommand } from "../bridge/file-bridge.js";
|
|
3
3
|
export function getUtilityTools(bridgeOptions) {
|
|
4
4
|
return {
|
|
@@ -33,6 +33,7 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
33
33
|
properties: {
|
|
34
34
|
item_ids: {
|
|
35
35
|
type: "array",
|
|
36
|
+
items: { type: "string" },
|
|
36
37
|
description: "Array of node IDs or names of items to delete",
|
|
37
38
|
},
|
|
38
39
|
},
|
|
@@ -209,12 +210,20 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
209
210
|
properties: {
|
|
210
211
|
frame_rate: {
|
|
211
212
|
type: "number",
|
|
213
|
+
minimum: 1,
|
|
214
|
+
maximum: 240,
|
|
212
215
|
description: "New frame rate (e.g., 23.976, 24, 25, 29.97, 30, 50, 59.94, 60)",
|
|
213
216
|
},
|
|
214
217
|
},
|
|
215
218
|
required: ["frame_rate"],
|
|
216
219
|
},
|
|
217
220
|
handler: async (args) => {
|
|
221
|
+
if (!Number.isFinite(args.frame_rate) || args.frame_rate < 1 || args.frame_rate > 240) {
|
|
222
|
+
return {
|
|
223
|
+
success: false,
|
|
224
|
+
error: "frame_rate must be a finite value between 1 and 240 fps",
|
|
225
|
+
};
|
|
226
|
+
}
|
|
218
227
|
const script = buildToolScript(`
|
|
219
228
|
var seq = app.project.activeSequence;
|
|
220
229
|
if (!seq) return __error("No active sequence");
|
|
@@ -222,10 +231,30 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
222
231
|
var settings = seq.getSettings();
|
|
223
232
|
if (!settings) return __error("Could not get sequence settings");
|
|
224
233
|
|
|
225
|
-
|
|
234
|
+
var requestedFps = ${args.frame_rate};
|
|
235
|
+
var requestedTicks = Math.round(TICKS_PER_SECOND / requestedFps);
|
|
236
|
+
var frameDuration = new Time();
|
|
237
|
+
frameDuration.ticks = requestedTicks.toString();
|
|
238
|
+
settings.videoFrameRate = frameDuration;
|
|
226
239
|
seq.setSettings(settings);
|
|
227
240
|
|
|
228
|
-
|
|
241
|
+
var applied = seq.getSettings();
|
|
242
|
+
if (!applied || !applied.videoFrameRate) {
|
|
243
|
+
return __error("Premiere did not return the updated sequence frame rate");
|
|
244
|
+
}
|
|
245
|
+
var appliedTicks = parseFloat(applied.videoFrameRate.ticks);
|
|
246
|
+
if (!isFinite(appliedTicks) || Math.abs(appliedTicks - requestedTicks) > 1) {
|
|
247
|
+
return __error(
|
|
248
|
+
"Premiere did not apply the requested frame rate: expected " +
|
|
249
|
+
requestedTicks + " ticks/frame, got " + appliedTicks
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return __result({
|
|
254
|
+
frameRate: requestedFps,
|
|
255
|
+
ticksPerFrame: requestedTicks.toString(),
|
|
256
|
+
sequence: seq.name
|
|
257
|
+
});
|
|
229
258
|
`);
|
|
230
259
|
return sendCommand(script, bridgeOptions);
|
|
231
260
|
},
|
|
@@ -582,7 +611,13 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
582
611
|
properties: {
|
|
583
612
|
marker_type: {
|
|
584
613
|
type: "string",
|
|
585
|
-
enum: [
|
|
614
|
+
enum: [
|
|
615
|
+
"Comment",
|
|
616
|
+
"Chapter",
|
|
617
|
+
"Segmentation",
|
|
618
|
+
"WebLink",
|
|
619
|
+
"FlashCuePoint",
|
|
620
|
+
],
|
|
586
621
|
description: "Type of marker to filter",
|
|
587
622
|
},
|
|
588
623
|
sequence_id: {
|
|
@@ -706,11 +741,13 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
706
741
|
${args.name ? `marker.name = "${escapeForExtendScript(args.name)}";` : ""}
|
|
707
742
|
${args.comments ? `marker.comments = "${escapeForExtendScript(args.comments)}";` : ""}
|
|
708
743
|
${args.type ? `marker.type = "${escapeForExtendScript(args.type)}";` : ""}
|
|
709
|
-
${args.duration_seconds !== undefined
|
|
744
|
+
${args.duration_seconds !== undefined
|
|
745
|
+
? `
|
|
710
746
|
var endTime = new Time();
|
|
711
747
|
endTime.seconds = ${args.time_seconds + args.duration_seconds};
|
|
712
748
|
marker.end = endTime;
|
|
713
|
-
`
|
|
749
|
+
`
|
|
750
|
+
: ""}
|
|
714
751
|
${args.color_index !== undefined ? `marker.setColorByIndex(${args.color_index});` : ""}
|
|
715
752
|
|
|
716
753
|
return __result({ added: true, item: item.name, timeSeconds: ${args.time_seconds} });
|
|
@@ -967,14 +1004,22 @@ export function getUtilityTools(bridgeOptions) {
|
|
|
967
1004
|
if (!project) return __error("No project open");
|
|
968
1005
|
|
|
969
1006
|
var set = {};
|
|
970
|
-
${args.captured_video
|
|
971
|
-
|
|
972
|
-
${args.
|
|
973
|
-
|
|
974
|
-
${args.
|
|
975
|
-
|
|
976
|
-
${args.
|
|
977
|
-
|
|
1007
|
+
${args.captured_video
|
|
1008
|
+
? `
|
|
1009
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.captured_video)}", 0); set.capturedVideo = "${escapeForExtendScript(args.captured_video)}"; } catch(e) {}`
|
|
1010
|
+
: ""}
|
|
1011
|
+
${args.captured_audio
|
|
1012
|
+
? `
|
|
1013
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.captured_audio)}", 1); set.capturedAudio = "${escapeForExtendScript(args.captured_audio)}"; } catch(e) {}`
|
|
1014
|
+
: ""}
|
|
1015
|
+
${args.video_previews
|
|
1016
|
+
? `
|
|
1017
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.video_previews)}", 2); set.videoPreviews = "${escapeForExtendScript(args.video_previews)}"; } catch(e) {}`
|
|
1018
|
+
: ""}
|
|
1019
|
+
${args.audio_previews
|
|
1020
|
+
? `
|
|
1021
|
+
try { project.setScratchDiskPath("${escapeForExtendScript(args.audio_previews)}", 3); set.audioPreviews = "${escapeForExtendScript(args.audio_previews)}"; } catch(e) {}`
|
|
1022
|
+
: ""}
|
|
978
1023
|
|
|
979
1024
|
return __result(set);
|
|
980
1025
|
`);
|
|
@@ -23,8 +23,8 @@ export declare const WORKFLOW_CATALOG: readonly [{
|
|
|
23
23
|
export declare const WORKFLOW_RESOURCE: string;
|
|
24
24
|
export declare const WORKFLOW_PROMPTS: {
|
|
25
25
|
name: string;
|
|
26
|
-
title: "Assemble a rough cut" | "
|
|
27
|
-
description: "Inspect
|
|
26
|
+
title: "Assemble a rough cut" | "Caption and style a sequence" | "Clean up dialogue" | "Prepare a delivery export";
|
|
27
|
+
description: "Inspect audio tracks, normalize dialogue, apply conservative cleanup, and verify levels before saving." | "Inspect the active sequence, create captions, apply styling, verify timing, and save." | "Inspect the project, import media, create or select a sequence, assemble clips, then verify and save." | "Validate the sequence and destination, export with an explicit preset, then report the produced artifact.";
|
|
28
28
|
argsSchema: {
|
|
29
29
|
goal: z.ZodString;
|
|
30
30
|
constraints: z.ZodOptional<z.ZodString>;
|
|
@@ -2,12 +2,12 @@ import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
|
2
2
|
/** Conservative MCP hints. They describe expected behavior, never authorization. */
|
|
3
3
|
export declare function annotationsForTool(name: string): ToolAnnotations;
|
|
4
4
|
export declare function structuredToolResult(tool: string, success: boolean, data?: unknown, error?: string): {
|
|
5
|
-
data: {} | null;
|
|
6
5
|
ok: boolean;
|
|
7
6
|
tool: string;
|
|
7
|
+
data: {} | null;
|
|
8
8
|
} | {
|
|
9
|
-
error: string;
|
|
10
9
|
ok: boolean;
|
|
11
10
|
tool: string;
|
|
11
|
+
error: string;
|
|
12
12
|
};
|
|
13
13
|
//# sourceMappingURL=tool-metadata.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "premiere-pro-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Adobe Premiere Pro MCP server with 269 AI video editing tools for timeline automation, effects, media management, and export.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"dist/**/*.js",
|
|
13
13
|
"dist/**/*.d.ts",
|
|
14
14
|
"cep-plugin",
|
|
15
|
+
"artifacts/MCPBridgeCEP.zxp",
|
|
15
16
|
"uxp-plugin",
|
|
16
17
|
"scripts",
|
|
17
18
|
"README.md",
|
|
@@ -70,15 +71,19 @@
|
|
|
70
71
|
"registry": "https://registry.npmjs.org/"
|
|
71
72
|
},
|
|
72
73
|
"engines": {
|
|
73
|
-
"node": ">=
|
|
74
|
+
"node": ">=20.19.0"
|
|
74
75
|
},
|
|
75
76
|
"dependencies": {
|
|
76
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
77
|
-
"zod": "^
|
|
77
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
78
|
+
"zod": "^4.4.3"
|
|
78
79
|
},
|
|
79
80
|
"devDependencies": {
|
|
80
|
-
"@types/node": "^
|
|
81
|
-
"typescript": "^
|
|
82
|
-
"vitest": "^
|
|
81
|
+
"@types/node": "^26.1.1",
|
|
82
|
+
"typescript": "^7.0.2",
|
|
83
|
+
"vitest": "^4.1.10"
|
|
84
|
+
},
|
|
85
|
+
"overrides": {
|
|
86
|
+
"@hono/node-server": "^2.0.5",
|
|
87
|
+
"body-parser": "^2.3.0"
|
|
83
88
|
}
|
|
84
89
|
}
|
|
@@ -138,8 +138,8 @@ REQUIREMENTS
|
|
|
138
138
|
SUPPORT
|
|
139
139
|
=======
|
|
140
140
|
|
|
141
|
-
GitHub: https://github.com/
|
|
142
|
-
Issues: https://github.com/
|
|
141
|
+
GitHub: https://github.com/leancoderkavy/premiere-pro-mcp
|
|
142
|
+
Issues: https://github.com/leancoderkavy/premiere-pro-mcp/issues
|
|
143
143
|
README_EOF
|
|
144
144
|
|
|
145
145
|
echo "✓ README created"
|
|
@@ -260,8 +260,8 @@ REQUIREMENTS
|
|
|
260
260
|
SUPPORT
|
|
261
261
|
=======
|
|
262
262
|
|
|
263
|
-
GitHub: https://github.com/
|
|
264
|
-
Issues: https://github.com/
|
|
263
|
+
GitHub: https://github.com/leancoderkavy/premiere-pro-mcp
|
|
264
|
+
Issues: https://github.com/leancoderkavy/premiere-pro-mcp/issues
|
|
265
265
|
README_EOF
|
|
266
266
|
|
|
267
267
|
echo "✓ README created"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$OutputPath = "",
|
|
3
|
+
[string]$ZxpSignCmdPath = "",
|
|
4
|
+
[string]$CertificatePath = "",
|
|
5
|
+
[string]$CertificatePassword = ""
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
$ErrorActionPreference = "Stop"
|
|
9
|
+
|
|
10
|
+
$projectDir = Split-Path -Parent $PSScriptRoot
|
|
11
|
+
$pluginSource = Join-Path $projectDir "cep-plugin"
|
|
12
|
+
if (-not $OutputPath) {
|
|
13
|
+
$OutputPath = Join-Path $projectDir "artifacts\MCPBridgeCEP.zxp"
|
|
14
|
+
}
|
|
15
|
+
$OutputPath = [System.IO.Path]::GetFullPath($OutputPath)
|
|
16
|
+
$outputDir = Split-Path -Parent $OutputPath
|
|
17
|
+
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
|
|
18
|
+
|
|
19
|
+
$temporaryRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("premiere-pro-mcp-zxp-" + [guid]::NewGuid().ToString("N"))
|
|
20
|
+
New-Item -ItemType Directory -Path $temporaryRoot | Out-Null
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
if (-not $ZxpSignCmdPath) {
|
|
24
|
+
$ZxpSignCmdPath = Join-Path $temporaryRoot "ZXPSignCmd.exe"
|
|
25
|
+
$downloadUrl = "https://raw.githubusercontent.com/Adobe-CEP/CEP-Resources/ab5e4e3e53a42fad08e1225a22a991bb1ffe73f6/ZXPSignCMD/4.1.103/win64/ZXPSignCmd.exe"
|
|
26
|
+
Invoke-WebRequest -Uri $downloadUrl -OutFile $ZxpSignCmdPath
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (-not (Test-Path -LiteralPath $ZxpSignCmdPath)) {
|
|
30
|
+
throw "ZXPSignCmd was not found at $ZxpSignCmdPath"
|
|
31
|
+
}
|
|
32
|
+
if (-not (Test-Path -LiteralPath (Join-Path $pluginSource "CSXS\manifest.xml"))) {
|
|
33
|
+
throw "CEP plugin manifest not found at $pluginSource"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (-not $CertificatePassword) {
|
|
37
|
+
$CertificatePassword = [guid]::NewGuid().ToString("N")
|
|
38
|
+
}
|
|
39
|
+
if (-not $CertificatePath) {
|
|
40
|
+
$CertificatePath = Join-Path $temporaryRoot "premiere-pro-mcp-release.p12"
|
|
41
|
+
& $ZxpSignCmdPath -selfSignedCert US California "Premiere Pro MCP" "Premiere Pro MCP" $CertificatePassword $CertificatePath
|
|
42
|
+
if ($LASTEXITCODE -ne 0) {
|
|
43
|
+
throw "ZXPSignCmd failed to create the release certificate."
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Test-Path -LiteralPath $OutputPath) {
|
|
48
|
+
Remove-Item -LiteralPath $OutputPath -Force
|
|
49
|
+
}
|
|
50
|
+
& $ZxpSignCmdPath -sign $pluginSource $OutputPath $CertificatePath $CertificatePassword
|
|
51
|
+
if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $OutputPath)) {
|
|
52
|
+
throw "ZXPSignCmd failed to create $OutputPath"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
& $ZxpSignCmdPath -verify $OutputPath
|
|
56
|
+
if ($LASTEXITCODE -ne 0) {
|
|
57
|
+
throw "ZXPSignCmd could not verify $OutputPath"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Write-Host "Signed CEP package verified: $OutputPath"
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
if (Test-Path -LiteralPath $temporaryRoot) {
|
|
64
|
+
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force
|
|
65
|
+
}
|
|
66
|
+
}
|
package/scripts/install-cep.ps1
CHANGED
|
@@ -6,6 +6,7 @@ $ErrorActionPreference = "Stop"
|
|
|
6
6
|
|
|
7
7
|
$projectDir = Split-Path -Parent $PSScriptRoot
|
|
8
8
|
$pluginSource = Join-Path $projectDir "cep-plugin"
|
|
9
|
+
$signedPackage = Join-Path $projectDir "artifacts\MCPBridgeCEP.zxp"
|
|
9
10
|
$cepRoot = Join-Path $env:APPDATA "Adobe\CEP\extensions"
|
|
10
11
|
$pluginDestination = Join-Path $cepRoot "MCPBridgeCEP"
|
|
11
12
|
$resolvedCepRoot = [System.IO.Path]::GetFullPath($cepRoot).TrimEnd([System.IO.Path]::DirectorySeparatorChar)
|
|
@@ -29,7 +30,23 @@ if (-not $Diagnose) {
|
|
|
29
30
|
if (Test-Path -LiteralPath $pluginDestination) {
|
|
30
31
|
Remove-Item -LiteralPath $resolvedDestination -Recurse -Force
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
if (Test-Path -LiteralPath $signedPackage) {
|
|
34
|
+
$temporaryZip = Join-Path ([System.IO.Path]::GetTempPath()) ("MCPBridgeCEP-" + [guid]::NewGuid().ToString("N") + ".zip")
|
|
35
|
+
try {
|
|
36
|
+
Copy-Item -LiteralPath $signedPackage -Destination $temporaryZip
|
|
37
|
+
Expand-Archive -LiteralPath $temporaryZip -DestinationPath $pluginDestination
|
|
38
|
+
Write-Host "Installed signed CEP package: $signedPackage"
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
if (Test-Path -LiteralPath $temporaryZip) {
|
|
42
|
+
Remove-Item -LiteralPath $temporaryZip -Force
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
Copy-Item -LiteralPath $pluginSource -Destination $pluginDestination -Recurse
|
|
48
|
+
Write-Warning "No signed CEP package is present; installed the development bundle and enabled PlayerDebugMode."
|
|
49
|
+
}
|
|
33
50
|
|
|
34
51
|
# Adobe requires PlayerDebugMode to be a String value. A DWORD that happens
|
|
35
52
|
# to contain 1 is ignored by CEP and the unsigned extension is not discovered.
|
|
@@ -59,10 +76,24 @@ foreach ($version in 9..14) {
|
|
|
59
76
|
}
|
|
60
77
|
}
|
|
61
78
|
|
|
79
|
+
$signatureFailures = Get-ChildItem -Path $env:TEMP -Filter "CEP*-PPRO.log" -File -ErrorAction SilentlyContinue |
|
|
80
|
+
Sort-Object LastWriteTime -Descending |
|
|
81
|
+
Select-Object -First 5 |
|
|
82
|
+
Select-String -Pattern "Signature verification failed for extension com\.mcp\.premiere\.bridge" -ErrorAction SilentlyContinue
|
|
83
|
+
if ($signatureFailures) {
|
|
84
|
+
$latestFailure = $signatureFailures | Select-Object -First 1
|
|
85
|
+
$problems += "Premiere logged a signature failure in $($latestFailure.Path). Reinstall from a release containing artifacts\MCPBridgeCEP.zxp, fully quit Premiere, and relaunch it."
|
|
86
|
+
}
|
|
87
|
+
|
|
62
88
|
if ($problems.Count -gt 0) {
|
|
63
89
|
Write-Error ($problems -join [Environment]::NewLine)
|
|
64
90
|
exit 1
|
|
65
91
|
}
|
|
66
92
|
|
|
67
93
|
Write-Host ""
|
|
68
|
-
|
|
94
|
+
if ($Diagnose) {
|
|
95
|
+
Write-Host "CEP diagnostics passed."
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
Write-Host "Installation verified. Restart Premiere Pro, then open Window > Extensions > MCP Bridge."
|
|
99
|
+
}
|
package/uxp-plugin/manifest.json
CHANGED