@synthetic-ai/premiere-mcp 2.1.0 → 2.3.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +135 -123
  2. package/LICENSE +21 -21
  3. package/README.md +242 -242
  4. package/cep-plugin/.debug +8 -8
  5. package/cep-plugin/CSInterface.js +92 -92
  6. package/cep-plugin/host.jsx +7 -7
  7. package/cep-plugin/index.html +472 -472
  8. package/cep-plugin/main.js +6 -0
  9. package/cep-plugin/premiere.jsx +24947 -24947
  10. package/dist/bridge/script-builder.js +378 -378
  11. package/dist/index.js +103 -4
  12. package/dist/license.js +38 -0
  13. package/dist/server.js +60 -60
  14. package/dist/tools/advanced.js +357 -357
  15. package/dist/tools/audio-advanced.js +1049 -1049
  16. package/dist/tools/audio.js +42 -42
  17. package/dist/tools/captions.js +27 -27
  18. package/dist/tools/clipboard.js +214 -214
  19. package/dist/tools/color-advanced.js +253 -253
  20. package/dist/tools/discovery.js +291 -291
  21. package/dist/tools/effects.js +285 -285
  22. package/dist/tools/export-presets.js +206 -206
  23. package/dist/tools/export.js +255 -255
  24. package/dist/tools/health.js +10 -10
  25. package/dist/tools/inspection.js +885 -885
  26. package/dist/tools/keyframes.js +369 -369
  27. package/dist/tools/markers.js +89 -89
  28. package/dist/tools/media.js +178 -178
  29. package/dist/tools/metadata.js +94 -94
  30. package/dist/tools/multicam.js +50 -50
  31. package/dist/tools/playback.js +15 -15
  32. package/dist/tools/playhead.js +95 -95
  33. package/dist/tools/project-manager.js +21 -21
  34. package/dist/tools/project.js +149 -149
  35. package/dist/tools/scripting.js +319 -319
  36. package/dist/tools/selection.js +202 -202
  37. package/dist/tools/sequence-advanced.js +379 -379
  38. package/dist/tools/sequence-settings.js +564 -564
  39. package/dist/tools/sequence.js +167 -167
  40. package/dist/tools/source-monitor.js +68 -68
  41. package/dist/tools/text.js +58 -58
  42. package/dist/tools/timeline.js +312 -312
  43. package/dist/tools/track-management.js +446 -446
  44. package/dist/tools/track-targeting.js +635 -635
  45. package/dist/tools/tracks.js +87 -87
  46. package/dist/tools/transitions-motion.js +174 -174
  47. package/dist/tools/transitions.js +111 -111
  48. package/dist/tools/utility.js +606 -606
  49. package/dist/tools/workspace.js +29 -29
  50. package/package.json +66 -66
  51. package/scripts/build-chat-dmg.sh +210 -210
  52. package/scripts/build-chat-zip.sh +291 -291
  53. package/scripts/install-cep-windows.ps1 +99 -99
  54. package/scripts/install-cep.sh +66 -66
  55. package/scripts/install-chat-plugin.bat +67 -67
  56. package/scripts/install-chat-plugin.sh +85 -85
  57. package/scripts/install-windows.bat +95 -95
  58. package/scripts/package.mjs +254 -254
package/dist/index.js CHANGED
@@ -2,12 +2,102 @@
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 { checkLicense } from "./license.js";
5
6
  import { execSync } from "child_process";
6
7
  import { fileURLToPath } from "url";
7
8
  import path from "path";
9
+ import { existsSync, mkdirSync, writeFileSync, unlinkSync } from "fs";
8
10
  const __filename = fileURLToPath(import.meta.url);
9
11
  const __dirname = path.dirname(__filename);
10
12
  const projectRoot = path.resolve(__dirname, "..");
13
+ // ---------------------------------------------------------------------------
14
+ // --doctor — standalone diagnostics, no MCP client or Premiere Pro required
15
+ // to run it. Prints a PASS/WARN/FAIL summary and exits 1 if anything failed,
16
+ // so it's also usable in a script (`premiere-mcp --doctor || echo "broken"`).
17
+ // Defined before the flag-handling block below since it's called from there.
18
+ // ---------------------------------------------------------------------------
19
+ const GREEN = "\x1b[32m";
20
+ const RED = "\x1b[31m";
21
+ const YELLOW = "\x1b[33m";
22
+ const DIM = "\x1b[2m";
23
+ const RESET = "\x1b[0m";
24
+ function printCheck(result, label, detail) {
25
+ const icon = result === "pass" ? `${GREEN}✓${RESET}` : result === "warn" ? `${YELLOW}!${RESET}` : `${RED}✗${RESET}`;
26
+ console.log(` ${icon} ${label}${detail ? `\n ${DIM}${detail}${RESET}` : ""}`);
27
+ }
28
+ function premiereInstallCandidates() {
29
+ const years = ["2026", "2025", "2024", "2023", "2022"];
30
+ if (process.platform === "darwin") {
31
+ return years.map((y) => `/Applications/Adobe Premiere Pro ${y}/Adobe Premiere Pro ${y}.app`);
32
+ }
33
+ return years.map((y) => `C:\\Program Files\\Adobe\\Adobe Premiere Pro ${y}\\Adobe Premiere Pro.exe`);
34
+ }
35
+ // Returns whether any check failed — the caller sets process.exitCode rather
36
+ // than us calling process.exit() here. On Windows, forcing process.exit()
37
+ // immediately after an in-flight fetch/AbortController teardown (the live
38
+ // license check below) can crash with a libuv assertion
39
+ // ("UV_HANDLE_CLOSING", src/win/async.c) before the process actually exits.
40
+ // Setting exitCode and letting the event loop drain naturally avoids it.
41
+ async function runDoctor() {
42
+ console.log(`\n${DIM}premiere-mcp doctor — checking your setup${RESET}\n`);
43
+ let hasFail = false;
44
+ // 1. Node version
45
+ const nodeMajor = parseInt(process.version.slice(1).split(".")[0], 10);
46
+ if (nodeMajor >= 18) {
47
+ printCheck("pass", `Node.js ${process.version}`);
48
+ }
49
+ else {
50
+ hasFail = true;
51
+ printCheck("fail", `Node.js ${process.version}`, "Requires Node 18 or newer — update from nodejs.org");
52
+ }
53
+ // 2. OS (informational — both are supported, this just confirms detection)
54
+ const osLabel = process.platform === "darwin" ? "macOS" : process.platform === "win32" ? "Windows" : process.platform;
55
+ printCheck(process.platform === "darwin" || process.platform === "win32" ? "pass" : "warn", `OS: ${osLabel}`);
56
+ // 3. Premiere Pro install detected on disk
57
+ const found = premiereInstallCandidates().find((p) => existsSync(p));
58
+ if (found) {
59
+ printCheck("pass", "Premiere Pro detected", found);
60
+ }
61
+ else {
62
+ printCheck("warn", "Premiere Pro not found in the usual install location", "Not fatal — the MCP server only needs Premiere Pro running when a tool actually calls it.");
63
+ }
64
+ // 4. License key present
65
+ const licenseKey = process.env.PREMIERE_PRO_MCP_LICENSE;
66
+ if (!licenseKey) {
67
+ hasFail = true;
68
+ printCheck("fail", "PREMIERE_PRO_MCP_LICENSE not set", "Add it to your MCP client config (claude_desktop_config.json or equivalent).");
69
+ }
70
+ else {
71
+ printCheck("pass", `License key present (${licenseKey.slice(0, 8)}...)`);
72
+ // 5. Live validation against synthetic.com.ar (also exercises network reachability)
73
+ const result = await checkLicense();
74
+ if (result.valid) {
75
+ printCheck("pass", "License validates", result.expiresAt ? `Expires: ${result.expiresAt}` : "No expiration");
76
+ }
77
+ else {
78
+ hasFail = true;
79
+ printCheck("fail", "License validation failed", result.message ?? "Unknown reason");
80
+ }
81
+ }
82
+ // 6. Bridge temp directory writable
83
+ const tempDir = getTempDir();
84
+ try {
85
+ if (!existsSync(tempDir))
86
+ mkdirSync(tempDir, { recursive: true, mode: 0o700 });
87
+ const probe = path.join(tempDir, `.doctor-probe-${Date.now()}`);
88
+ writeFileSync(probe, "ok");
89
+ unlinkSync(probe);
90
+ printCheck("pass", "Bridge temp directory writable", tempDir);
91
+ }
92
+ catch (err) {
93
+ hasFail = true;
94
+ printCheck("fail", "Bridge temp directory not writable", `${tempDir} — ${err instanceof Error ? err.message : String(err)}`);
95
+ }
96
+ console.log(hasFail
97
+ ? `\n${RED}Some checks failed.${RESET} Fix the items above, or share this output with support at https://synthetic.com.ar/dashboard/support\n`
98
+ : `\n${GREEN}Everything looks good.${RESET}\n`);
99
+ return hasFail;
100
+ }
11
101
  // Handle CLI flags
12
102
  const args = process.argv.slice(2);
13
103
  if (args.includes("--help") || args.includes("-h")) {
@@ -16,6 +106,7 @@ premiere-pro-mcp — MCP server for Adobe Premiere Pro (437 tools)
16
106
 
17
107
  Usage:
18
108
  premiere-pro-mcp Start the MCP server (stdio transport)
109
+ premiere-pro-mcp --doctor Check your setup (Node, license, Premiere Pro, temp dir)
19
110
  premiere-pro-mcp --install-cep Install the CEP plugin into Premiere Pro
20
111
  premiere-pro-mcp --help Show this help message
21
112
  premiere-pro-mcp --version Show version
@@ -33,6 +124,12 @@ if (args.includes("--version") || args.includes("-v")) {
33
124
  console.log(pkg.default.version);
34
125
  process.exit(0);
35
126
  }
127
+ let ranAsFlag = false;
128
+ if (args.includes("--doctor")) {
129
+ const hasFail = await runDoctor();
130
+ process.exitCode = hasFail ? 1 : 0;
131
+ ranAsFlag = true;
132
+ }
36
133
  if (args.includes("--install-cep")) {
37
134
  const scriptPath = path.join(projectRoot, "scripts", "install-cep.sh");
38
135
  console.log("Installing CEP plugin...\n");
@@ -63,8 +160,10 @@ async function main() {
63
160
  await server.connect(transport);
64
161
  console.error(`[premiere-pro-mcp] Server connected and ready`);
65
162
  }
66
- main().catch((err) => {
67
- console.error("[premiere-pro-mcp] Fatal error:", err);
68
- process.exit(1);
69
- });
163
+ if (!ranAsFlag) {
164
+ main().catch((err) => {
165
+ console.error("[premiere-pro-mcp] Fatal error:", err);
166
+ process.exit(1);
167
+ });
168
+ }
70
169
  //# sourceMappingURL=index.js.map
package/dist/license.js CHANGED
@@ -3,9 +3,45 @@
3
3
  * Same pattern as ae-mcp/src/server.mjs and photoshop-mcp/server.mjs:
4
4
  * validate once, cache for an hour, let diagnostic tools through for free.
5
5
  */
6
+ import os from "node:os";
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import crypto from "node:crypto";
6
10
  const LICENSE_KEY = process.env.PREMIERE_PRO_MCP_LICENSE;
7
11
  const LICENSE_VALIDATION_URL = "https://synthetic.com.ar/api/v1/license/validate";
8
12
  const LICENSE_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
13
+ // Device identity (for the 2-device license cap) — shared across all
14
+ // Synthetic MCP packages on purpose: one physical machine should count as
15
+ // ONE device against the cap, not one per product installed on it. See
16
+ // photoshop-mcp/server.mjs's getMachineId() for the identical logic.
17
+ function getMachineId() {
18
+ try {
19
+ const dir = path.join(os.homedir(), ".synthetic");
20
+ const file = path.join(dir, "device-id");
21
+ if (fs.existsSync(file)) {
22
+ const id = fs.readFileSync(file, "utf8").trim();
23
+ if (id)
24
+ return id;
25
+ }
26
+ fs.mkdirSync(dir, { recursive: true });
27
+ const id = crypto.randomUUID();
28
+ fs.writeFileSync(file, id, "utf8");
29
+ return id;
30
+ }
31
+ catch {
32
+ return "volatile-" + crypto.randomUUID();
33
+ }
34
+ }
35
+ function getDeviceLabel() {
36
+ try {
37
+ return `${os.hostname()} (${process.platform})`;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ const MACHINE_ID = getMachineId();
44
+ const DEVICE_LABEL = getDeviceLabel();
9
45
  let cache = null;
10
46
  async function postJson(url, body) {
11
47
  try {
@@ -41,6 +77,8 @@ export async function checkLicense() {
41
77
  const result = await postJson(LICENSE_VALIDATION_URL, {
42
78
  key: LICENSE_KEY,
43
79
  product: "premiere-mcp",
80
+ machineId: MACHINE_ID,
81
+ deviceLabel: DEVICE_LABEL,
44
82
  });
45
83
  if (result) {
46
84
  cache = { ...result, checkedAt: Date.now() };
package/dist/server.js CHANGED
@@ -38,66 +38,66 @@ import { getSequenceSettingsTools } from "./tools/sequence-settings.js";
38
38
  import { EXTENDSCRIPT_REFERENCE } from "./resources/extendscript-reference.js";
39
39
  import { checkLicense, licenseErrorResponse, FREE_TOOLS } from "./license.js";
40
40
  import { z } from "zod";
41
- const PREMIERE_INSTRUCTIONS = `You are controlling Adobe Premiere Pro through MCP tools. Follow these best practices:
42
-
43
- WORKFLOW ORDER:
44
- 1. Always call get_project_info first to understand the current state.
45
- 2. Import media before adding to timeline.
46
- 3. Create/select a sequence before timeline operations.
47
- 4. Add clips first, then effects, then transitions.
48
- 5. Save the project after making significant changes.
49
-
50
- TIMELINE RULES:
51
- - Clips are identified by node_id. Use get_active_sequence or list_sequence_tracks to discover node IDs.
52
- - Video clips on higher track indices appear on top of lower ones (compositing order).
53
- - Images default to ~5 seconds duration when added to timeline.
54
- - The first clip added to a new sequence determines its resolution and frame rate.
55
- - Time values are in seconds (the tools handle tick conversion internally).
56
-
57
- EFFECTS & TRANSITIONS:
58
- - Apply effects by name using apply_effect (e.g., "Gaussian Blur", "Lumetri Color").
59
- - Use list_available_effects to find exact effect names.
60
- - Transitions require clips to be adjacent (no gap between them).
61
- - Keep transitions short (0.5-2 seconds typically).
62
- - Use color_correct for Lumetri Color adjustments rather than manual property setting.
63
-
64
- KEYFRAMES:
65
- - Use get_effect_properties to discover property names before setting values.
66
- - Enable keyframes with add_keyframe; the property auto-enables time-varying.
67
- - Interpolation types: "linear" (smooth), "hold" (instant jump), "bezier" (custom easing).
68
-
69
- QE DOM TOOLS:
70
- - Tools marked "Uses QE DOM" use an undocumented API. They are powerful but may behave unexpectedly.
71
- - ripple_delete, roll_edit, slide_edit, slip_edit are QE-based advanced trim tools.
72
- - set_clip_speed_qe is more reliable than the ExtendScript speed method.
73
-
74
- CLIPS & SELECTION:
75
- - Use set_clip_selection to select clips before operations that work on selection (link, unlink, scene_edit_detection).
76
- - Use overwrite_clip for 3-point editing (overwrites existing content).
77
- - Use add_to_timeline for insert editing (ripples content forward).
78
-
79
- BINS & ORGANIZATION:
80
- - Bins are folders in the project panel. Use create_bin, delete_bin, rename_bin.
81
- - Use move_item_to_bin to organize imported media.
82
- - create_smart_bin creates auto-populating search bins.
83
-
84
- EXPORT:
85
- - Use export_sequence for AME-based encoding with presets.
86
- - Use export_frame to capture a single frame as an image.
87
- - Use start_batch_encode to begin rendering all queued items.
88
-
89
- ERROR HANDLING:
90
- - If a tool returns "No active sequence", call set_active_sequence first.
91
- - If a tool returns "Clip not found", the node_id may have changed after timeline edits. Re-query the sequence.
92
- - If "QE clip not found", the clip index may differ between DOM and QE. Try re-querying.
93
-
94
- CUSTOM SCRIPTING:
95
- - Use execute_extendscript to write and run any ExtendScript code for tasks not covered by existing tools.
96
- - Use evaluate_expression for quick one-line queries.
97
- - Use inspect_dom_object to explore unfamiliar objects.
98
- - Use get_premiere_state as your first call to understand the full current context.
99
- - Use get_sequence_structure for detailed timeline layout before edits.
100
- - Read the "extendscript-reference" resource for the complete API cheat sheet.
41
+ const PREMIERE_INSTRUCTIONS = `You are controlling Adobe Premiere Pro through MCP tools. Follow these best practices:
42
+
43
+ WORKFLOW ORDER:
44
+ 1. Always call get_project_info first to understand the current state.
45
+ 2. Import media before adding to timeline.
46
+ 3. Create/select a sequence before timeline operations.
47
+ 4. Add clips first, then effects, then transitions.
48
+ 5. Save the project after making significant changes.
49
+
50
+ TIMELINE RULES:
51
+ - Clips are identified by node_id. Use get_active_sequence or list_sequence_tracks to discover node IDs.
52
+ - Video clips on higher track indices appear on top of lower ones (compositing order).
53
+ - Images default to ~5 seconds duration when added to timeline.
54
+ - The first clip added to a new sequence determines its resolution and frame rate.
55
+ - Time values are in seconds (the tools handle tick conversion internally).
56
+
57
+ EFFECTS & TRANSITIONS:
58
+ - Apply effects by name using apply_effect (e.g., "Gaussian Blur", "Lumetri Color").
59
+ - Use list_available_effects to find exact effect names.
60
+ - Transitions require clips to be adjacent (no gap between them).
61
+ - Keep transitions short (0.5-2 seconds typically).
62
+ - Use color_correct for Lumetri Color adjustments rather than manual property setting.
63
+
64
+ KEYFRAMES:
65
+ - Use get_effect_properties to discover property names before setting values.
66
+ - Enable keyframes with add_keyframe; the property auto-enables time-varying.
67
+ - Interpolation types: "linear" (smooth), "hold" (instant jump), "bezier" (custom easing).
68
+
69
+ QE DOM TOOLS:
70
+ - Tools marked "Uses QE DOM" use an undocumented API. They are powerful but may behave unexpectedly.
71
+ - ripple_delete, roll_edit, slide_edit, slip_edit are QE-based advanced trim tools.
72
+ - set_clip_speed_qe is more reliable than the ExtendScript speed method.
73
+
74
+ CLIPS & SELECTION:
75
+ - Use set_clip_selection to select clips before operations that work on selection (link, unlink, scene_edit_detection).
76
+ - Use overwrite_clip for 3-point editing (overwrites existing content).
77
+ - Use add_to_timeline for insert editing (ripples content forward).
78
+
79
+ BINS & ORGANIZATION:
80
+ - Bins are folders in the project panel. Use create_bin, delete_bin, rename_bin.
81
+ - Use move_item_to_bin to organize imported media.
82
+ - create_smart_bin creates auto-populating search bins.
83
+
84
+ EXPORT:
85
+ - Use export_sequence for AME-based encoding with presets.
86
+ - Use export_frame to capture a single frame as an image.
87
+ - Use start_batch_encode to begin rendering all queued items.
88
+
89
+ ERROR HANDLING:
90
+ - If a tool returns "No active sequence", call set_active_sequence first.
91
+ - If a tool returns "Clip not found", the node_id may have changed after timeline edits. Re-query the sequence.
92
+ - If "QE clip not found", the clip index may differ between DOM and QE. Try re-querying.
93
+
94
+ CUSTOM SCRIPTING:
95
+ - Use execute_extendscript to write and run any ExtendScript code for tasks not covered by existing tools.
96
+ - Use evaluate_expression for quick one-line queries.
97
+ - Use inspect_dom_object to explore unfamiliar objects.
98
+ - Use get_premiere_state as your first call to understand the full current context.
99
+ - Use get_sequence_structure for detailed timeline layout before edits.
100
+ - Read the "extendscript-reference" resource for the complete API cheat sheet.
101
101
  `;
102
102
  /**
103
103
  * Convert a JSON Schema-style parameters object to a Zod shape for MCP SDK registration.