davinci-resolve-mcp 4.4.2 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/README.md +2 -2
- package/README.zh-CN.md +3 -3
- package/docs/SKILL.md +15 -0
- package/install.py +1 -1
- package/package.json +1 -1
- package/src/granular/common.py +2 -1
- package/src/granular/folder.py +4 -0
- package/src/granular/gallery.py +4 -0
- package/src/granular/graph.py +4 -0
- package/src/granular/media_pool.py +6 -0
- package/src/granular/media_pool_item.py +21 -0
- package/src/granular/project.py +28 -0
- package/src/granular/resolve_211.py +9 -0
- package/src/granular/resolve_control.py +9 -0
- package/src/granular/timeline.py +18 -0
- package/src/granular/timeline_item.py +30 -0
- package/src/server.py +1 -1
- package/src/utils/destructive_hook.py +216 -3
package/src/granular/project.py
CHANGED
|
@@ -61,6 +61,7 @@ def get_project_setting(setting_name: str) -> Dict[str, Any]:
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
64
|
+
@granular_destructive_op()
|
|
64
65
|
def set_project_setting(setting_name: str, setting_value: Any) -> str:
|
|
65
66
|
"""Set a project setting to the specified value.
|
|
66
67
|
|
|
@@ -250,6 +251,7 @@ def save_project() -> str:
|
|
|
250
251
|
|
|
251
252
|
|
|
252
253
|
@mcp.tool()
|
|
254
|
+
@granular_destructive_op()
|
|
253
255
|
def close_project() -> str:
|
|
254
256
|
"""Close the current project.
|
|
255
257
|
|
|
@@ -306,6 +308,7 @@ def get_cache_settings() -> Dict[str, Any]:
|
|
|
306
308
|
|
|
307
309
|
|
|
308
310
|
@mcp.tool()
|
|
311
|
+
@granular_destructive_op()
|
|
309
312
|
def set_cache_mode(mode: str) -> str:
|
|
310
313
|
"""Set cache mode for the current project.
|
|
311
314
|
|
|
@@ -340,6 +343,7 @@ def set_cache_mode(mode: str) -> str:
|
|
|
340
343
|
|
|
341
344
|
|
|
342
345
|
@mcp.tool()
|
|
346
|
+
@granular_destructive_op()
|
|
343
347
|
def set_optimized_media_mode(mode: str) -> str:
|
|
344
348
|
"""Set optimized media mode for the current project.
|
|
345
349
|
|
|
@@ -374,6 +378,7 @@ def set_optimized_media_mode(mode: str) -> str:
|
|
|
374
378
|
|
|
375
379
|
|
|
376
380
|
@mcp.tool()
|
|
381
|
+
@granular_destructive_op()
|
|
377
382
|
def set_proxy_mode(mode: str) -> str:
|
|
378
383
|
"""Set proxy media mode for the current project.
|
|
379
384
|
|
|
@@ -408,6 +413,7 @@ def set_proxy_mode(mode: str) -> str:
|
|
|
408
413
|
|
|
409
414
|
|
|
410
415
|
@mcp.tool()
|
|
416
|
+
@granular_destructive_op()
|
|
411
417
|
def set_proxy_quality(quality: str) -> str:
|
|
412
418
|
"""Set proxy media quality for the current project.
|
|
413
419
|
|
|
@@ -442,6 +448,7 @@ def set_proxy_quality(quality: str) -> str:
|
|
|
442
448
|
|
|
443
449
|
|
|
444
450
|
@mcp.tool()
|
|
451
|
+
@granular_destructive_op()
|
|
445
452
|
def set_cache_path(path_type: str, path: str) -> str:
|
|
446
453
|
"""Set cache file path for the current project.
|
|
447
454
|
|
|
@@ -501,6 +508,7 @@ def create_cloud_project_tool(
|
|
|
501
508
|
|
|
502
509
|
|
|
503
510
|
@mcp.tool()
|
|
511
|
+
@granular_destructive_op()
|
|
504
512
|
def load_cloud_project_tool(
|
|
505
513
|
project_name: Optional[str] = None,
|
|
506
514
|
project_media_path: Optional[str] = None,
|
|
@@ -594,6 +602,7 @@ def get_project_property_endpoint(property_name: str) -> Dict[str, Any]:
|
|
|
594
602
|
|
|
595
603
|
|
|
596
604
|
@mcp.tool()
|
|
605
|
+
@granular_destructive_op()
|
|
597
606
|
def set_project_property_tool(property_name: str, property_value: Any) -> str:
|
|
598
607
|
"""Set a project property value.
|
|
599
608
|
|
|
@@ -624,6 +633,7 @@ def get_timeline_format() -> Dict[str, Any]:
|
|
|
624
633
|
|
|
625
634
|
|
|
626
635
|
@mcp.tool()
|
|
636
|
+
@granular_destructive_op()
|
|
627
637
|
def set_timeline_format_tool(width: int, height: int, frame_rate: float, interlaced: bool = False) -> str:
|
|
628
638
|
"""Set timeline format (resolution and frame rate).
|
|
629
639
|
|
|
@@ -657,6 +667,7 @@ def get_superscale_settings_endpoint() -> Dict[str, Any]:
|
|
|
657
667
|
|
|
658
668
|
|
|
659
669
|
@mcp.tool()
|
|
670
|
+
@granular_destructive_op()
|
|
660
671
|
def set_superscale_settings_tool(enabled: bool, quality: int = 0) -> str:
|
|
661
672
|
"""Set SuperScale settings for the current project.
|
|
662
673
|
|
|
@@ -695,6 +706,7 @@ def get_color_settings_endpoint() -> Dict[str, Any]:
|
|
|
695
706
|
|
|
696
707
|
|
|
697
708
|
@mcp.tool()
|
|
709
|
+
@granular_destructive_op()
|
|
698
710
|
def set_color_science_mode_tool(mode: str) -> str:
|
|
699
711
|
"""Set color science mode for the current project.
|
|
700
712
|
|
|
@@ -714,6 +726,7 @@ def set_color_science_mode_tool(mode: str) -> str:
|
|
|
714
726
|
|
|
715
727
|
|
|
716
728
|
@mcp.tool()
|
|
729
|
+
@granular_destructive_op()
|
|
717
730
|
def set_color_space_tool(color_space: str, gamma: str = None) -> str:
|
|
718
731
|
"""Set timeline color space and gamma.
|
|
719
732
|
|
|
@@ -776,6 +789,7 @@ def archive_project(project_name: str, archive_path: str, archive_src_media: boo
|
|
|
776
789
|
|
|
777
790
|
|
|
778
791
|
@mcp.tool()
|
|
792
|
+
@granular_destructive_op()
|
|
779
793
|
def delete_project(project_name: str) -> Dict[str, Any]:
|
|
780
794
|
"""Delete a project from the current database. WARNING: This is irreversible.
|
|
781
795
|
|
|
@@ -810,6 +824,7 @@ def create_project_folder(folder_name: str) -> Dict[str, Any]:
|
|
|
810
824
|
|
|
811
825
|
|
|
812
826
|
@mcp.tool()
|
|
827
|
+
@granular_destructive_op()
|
|
813
828
|
def delete_project_folder(folder_name: str) -> Dict[str, Any]:
|
|
814
829
|
"""Delete a folder from the current project folder location.
|
|
815
830
|
|
|
@@ -953,6 +968,7 @@ def get_database_list() -> Dict[str, Any]:
|
|
|
953
968
|
|
|
954
969
|
|
|
955
970
|
@mcp.tool()
|
|
971
|
+
@granular_destructive_op()
|
|
956
972
|
def set_current_database(db_info: Dict[str, str]) -> Dict[str, Any]:
|
|
957
973
|
"""Switch to a different database.
|
|
958
974
|
|
|
@@ -968,6 +984,7 @@ def set_current_database(db_info: Dict[str, str]) -> Dict[str, Any]:
|
|
|
968
984
|
|
|
969
985
|
|
|
970
986
|
@mcp.tool()
|
|
987
|
+
@granular_destructive_op()
|
|
971
988
|
def set_project_name(name: str) -> Dict[str, Any]:
|
|
972
989
|
"""Rename the current project.
|
|
973
990
|
|
|
@@ -1017,6 +1034,7 @@ def get_project_preset_list() -> Dict[str, Any]:
|
|
|
1017
1034
|
|
|
1018
1035
|
|
|
1019
1036
|
@mcp.tool()
|
|
1037
|
+
@granular_destructive_op()
|
|
1020
1038
|
def set_project_preset(preset_name: str) -> Dict[str, Any]:
|
|
1021
1039
|
"""Apply a project preset to the current project.
|
|
1022
1040
|
|
|
@@ -1034,6 +1052,7 @@ def set_project_preset(preset_name: str) -> Dict[str, Any]:
|
|
|
1034
1052
|
|
|
1035
1053
|
|
|
1036
1054
|
@mcp.tool()
|
|
1055
|
+
@granular_destructive_op()
|
|
1037
1056
|
def delete_render_job(job_id: str) -> Dict[str, Any]:
|
|
1038
1057
|
"""Delete a specific render job by its ID.
|
|
1039
1058
|
|
|
@@ -1085,6 +1104,7 @@ def start_rendering_jobs(job_ids: Optional[List[str]] = None, is_interactive_mod
|
|
|
1085
1104
|
|
|
1086
1105
|
|
|
1087
1106
|
@mcp.tool()
|
|
1107
|
+
@granular_destructive_op()
|
|
1088
1108
|
def stop_rendering() -> Dict[str, Any]:
|
|
1089
1109
|
"""Stop the current rendering process."""
|
|
1090
1110
|
resolve = get_resolve()
|
|
@@ -1111,6 +1131,7 @@ def is_rendering_in_progress() -> Dict[str, Any]:
|
|
|
1111
1131
|
|
|
1112
1132
|
|
|
1113
1133
|
@mcp.tool()
|
|
1134
|
+
@granular_destructive_op()
|
|
1114
1135
|
def load_render_preset(preset_name: str) -> Dict[str, Any]:
|
|
1115
1136
|
"""Load a render preset by name.
|
|
1116
1137
|
|
|
@@ -1145,6 +1166,7 @@ def save_as_new_render_preset(preset_name: str) -> Dict[str, Any]:
|
|
|
1145
1166
|
|
|
1146
1167
|
|
|
1147
1168
|
@mcp.tool()
|
|
1169
|
+
@granular_destructive_op()
|
|
1148
1170
|
def delete_render_preset(preset_name: str) -> Dict[str, Any]:
|
|
1149
1171
|
"""Delete a render preset.
|
|
1150
1172
|
|
|
@@ -1162,6 +1184,7 @@ def delete_render_preset(preset_name: str) -> Dict[str, Any]:
|
|
|
1162
1184
|
|
|
1163
1185
|
|
|
1164
1186
|
@mcp.tool()
|
|
1187
|
+
@granular_destructive_op()
|
|
1165
1188
|
def set_render_settings(settings: Dict[str, Any]) -> Dict[str, Any]:
|
|
1166
1189
|
"""Set render settings for the current project.
|
|
1167
1190
|
|
|
@@ -1254,6 +1277,7 @@ def get_current_render_format_and_codec() -> Dict[str, Any]:
|
|
|
1254
1277
|
|
|
1255
1278
|
|
|
1256
1279
|
@mcp.tool()
|
|
1280
|
+
@granular_destructive_op()
|
|
1257
1281
|
def set_current_render_format_and_codec(format_name: str, codec_name: str) -> Dict[str, Any]:
|
|
1258
1282
|
"""Set the render format and codec.
|
|
1259
1283
|
|
|
@@ -1297,6 +1321,7 @@ def get_current_render_mode() -> Dict[str, Any]:
|
|
|
1297
1321
|
|
|
1298
1322
|
|
|
1299
1323
|
@mcp.tool()
|
|
1324
|
+
@granular_destructive_op()
|
|
1300
1325
|
def set_current_render_mode(mode: int) -> Dict[str, Any]:
|
|
1301
1326
|
"""Set the render mode.
|
|
1302
1327
|
|
|
@@ -1375,6 +1400,7 @@ def insert_audio_to_current_track(file_path: str) -> Dict[str, Any]:
|
|
|
1375
1400
|
|
|
1376
1401
|
|
|
1377
1402
|
@mcp.tool()
|
|
1403
|
+
@granular_destructive_op()
|
|
1378
1404
|
def load_burn_in_preset(preset_name: str) -> Dict[str, Any]:
|
|
1379
1405
|
"""Load a burn-in preset by name for the project.
|
|
1380
1406
|
|
|
@@ -1441,6 +1467,7 @@ def add_color_group(group_name: str) -> Dict[str, Any]:
|
|
|
1441
1467
|
|
|
1442
1468
|
|
|
1443
1469
|
@mcp.tool()
|
|
1470
|
+
@granular_destructive_op()
|
|
1444
1471
|
def delete_color_group(group_name: str) -> Dict[str, Any]:
|
|
1445
1472
|
"""Delete a color group from the current project.
|
|
1446
1473
|
|
|
@@ -1588,6 +1615,7 @@ def add_render_job() -> Dict[str, Any]:
|
|
|
1588
1615
|
|
|
1589
1616
|
|
|
1590
1617
|
@mcp.tool()
|
|
1618
|
+
@granular_destructive_op()
|
|
1591
1619
|
def load_cloud_project(project_name: str, project_media_path: str, sync_mode: str = "proxy") -> Dict[str, Any]:
|
|
1592
1620
|
"""Load a cloud project from DaVinci Resolve cloud.
|
|
1593
1621
|
|
|
@@ -9,6 +9,7 @@ from src.utils.resolve211_edits import validate_edit_options, validate_transitio
|
|
|
9
9
|
from src.granular.common import (
|
|
10
10
|
mcp, READ_ONLY_TOOL, WRITE_TOOL, DESTRUCTIVE_TOOL, get_resolve, get_current_project,
|
|
11
11
|
_get_timeline, _get_timeline_item, _resolve_safe_dir, _find_clip_by_id, _requires_method, has_method,
|
|
12
|
+
granular_destructive_op,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
|
|
@@ -190,6 +191,7 @@ def set_timeline_item_fades(options: dict, track_type: str = "video", track_inde
|
|
|
190
191
|
|
|
191
192
|
|
|
192
193
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
194
|
+
@granular_destructive_op()
|
|
193
195
|
def add_timeline_item_transition(options: dict, track_type: str = "video", track_index: int = 1, item_index: int = 0) -> dict:
|
|
194
196
|
"""Add a native 21.1 transition using type/category/position/alignment and optional duration in frames. Returns actual span; clip indexes can change after insertion."""
|
|
195
197
|
error = validate_transition_options(options)
|
|
@@ -207,6 +209,7 @@ def add_timeline_item_transition(options: dict, track_type: str = "video", track
|
|
|
207
209
|
|
|
208
210
|
|
|
209
211
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
212
|
+
@granular_destructive_op()
|
|
210
213
|
def create_multicam_clip(clip_ids: list[str], options: dict | None = None) -> dict:
|
|
211
214
|
"""Create native 21.1 multicam clips. Options follow MulticamOptions; named Resolve constants or numeric values accepted. Resolves every ID before writing."""
|
|
212
215
|
_, p = get_current_project()
|
|
@@ -220,6 +223,7 @@ def create_multicam_clip(clip_ids: list[str], options: dict | None = None) -> di
|
|
|
220
223
|
|
|
221
224
|
|
|
222
225
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
226
|
+
@granular_destructive_op()
|
|
223
227
|
def flatten_timeline_item_multicam(grade_option: str = "FLATTEN_MULTICAM_COPY_GRADE", track_type: str = "video", track_index: int = 1, item_index: int = 0) -> dict:
|
|
224
228
|
"""Flatten a native multicam item using COPY_GRADE or RETAIN_GRADE_FROM_ANGLE. Re-query items after replacement."""
|
|
225
229
|
if track_type not in ("video", "audio") or track_index < 1 or item_index < 0:
|
|
@@ -237,6 +241,7 @@ def flatten_timeline_item_multicam(grade_option: str = "FLATTEN_MULTICAM_COPY_GR
|
|
|
237
241
|
|
|
238
242
|
|
|
239
243
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
244
|
+
@granular_destructive_op()
|
|
240
245
|
def set_timeline_output_blanking(options: dict) -> dict:
|
|
241
246
|
"""Set native 21.1 timeline Top/Bottom/Left/Right pixel coordinates."""
|
|
242
247
|
error = validate_blanking(options)
|
|
@@ -252,6 +257,7 @@ def set_timeline_output_blanking(options: dict) -> dict:
|
|
|
252
257
|
|
|
253
258
|
|
|
254
259
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
260
|
+
@granular_destructive_op()
|
|
255
261
|
def set_timeline_item_output_blanking(options: dict, track_type: str = "video", track_index: int = 1, item_index: int = 0) -> dict:
|
|
256
262
|
"""Set native 21.1 clip pixel coordinates. Disable timeline blanking inheritance first; this call does not change inheritance."""
|
|
257
263
|
error = validate_blanking(options)
|
|
@@ -269,6 +275,7 @@ def set_timeline_item_output_blanking(options: dict, track_type: str = "video",
|
|
|
269
275
|
|
|
270
276
|
|
|
271
277
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
278
|
+
@granular_destructive_op()
|
|
272
279
|
def set_timeline_item_use_timeline_for_output_blanking(use_timeline: bool, track_type: str = "video", track_index: int = 1, item_index: int = 0) -> dict:
|
|
273
280
|
"""Explicitly enable/disable native 21.1 timeline blanking inheritance for a clip."""
|
|
274
281
|
if type(use_timeline) is not bool:
|
|
@@ -285,6 +292,7 @@ def set_timeline_item_use_timeline_for_output_blanking(use_timeline: bool, track
|
|
|
285
292
|
|
|
286
293
|
|
|
287
294
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
295
|
+
@granular_destructive_op()
|
|
288
296
|
def normalize_timeline_audio_level(item_ids: list[str], options: dict | None = None) -> dict:
|
|
289
297
|
"""Native 21.1 normalization of explicit audio timeline item IDs. Options normalizationMode, targetLevel (dBFS), targetLoudness (LKFS), setLevelMode; use get_normalize_audio_modes for names."""
|
|
290
298
|
_, timeline, error = _get_timeline()
|
|
@@ -297,6 +305,7 @@ def normalize_timeline_audio_level(item_ids: list[str], options: dict | None = N
|
|
|
297
305
|
|
|
298
306
|
|
|
299
307
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
308
|
+
@granular_destructive_op()
|
|
300
309
|
def auto_align_timeline_clips(item_ids: list[str], options: dict | None = None) -> dict:
|
|
301
310
|
"""Native 21.1 alignment of current video/audio items by unique ID. Include linked audio AND video IDs to move both; selection is not expanded. Options SyncUsing and UseTrack accept documented constant names or integral native values."""
|
|
302
311
|
_, timeline, error = _get_timeline()
|
|
@@ -228,6 +228,7 @@ def save_layout_preset_tool(preset_name: str) -> Dict[str, Any]:
|
|
|
228
228
|
|
|
229
229
|
|
|
230
230
|
@mcp.tool()
|
|
231
|
+
@granular_destructive_op()
|
|
231
232
|
def load_layout_preset_tool(preset_name: str) -> Dict[str, Any]:
|
|
232
233
|
"""Load a UI layout preset.
|
|
233
234
|
|
|
@@ -282,6 +283,7 @@ def import_layout_preset_tool(import_path: str, preset_name: str = None) -> Dict
|
|
|
282
283
|
|
|
283
284
|
|
|
284
285
|
@mcp.tool()
|
|
286
|
+
@granular_destructive_op()
|
|
285
287
|
def delete_layout_preset_tool(preset_name: str) -> Dict[str, Any]:
|
|
286
288
|
"""Delete a layout preset.
|
|
287
289
|
|
|
@@ -325,6 +327,7 @@ def get_app_state_endpoint() -> Dict[str, Any]:
|
|
|
325
327
|
|
|
326
328
|
|
|
327
329
|
@mcp.tool()
|
|
330
|
+
@granular_destructive_op()
|
|
328
331
|
def quit_app(force: bool = False, save_project: bool = True) -> str:
|
|
329
332
|
"""
|
|
330
333
|
Quit DaVinci Resolve application.
|
|
@@ -346,6 +349,7 @@ def quit_app(force: bool = False, save_project: bool = True) -> str:
|
|
|
346
349
|
|
|
347
350
|
|
|
348
351
|
@mcp.tool()
|
|
352
|
+
@granular_destructive_op()
|
|
349
353
|
def restart_app(wait_seconds: int = 5) -> str:
|
|
350
354
|
"""
|
|
351
355
|
Restart DaVinci Resolve application.
|
|
@@ -515,6 +519,7 @@ def get_keyframe_mode() -> Dict[str, Any]:
|
|
|
515
519
|
|
|
516
520
|
|
|
517
521
|
@mcp.tool()
|
|
522
|
+
@granular_destructive_op()
|
|
518
523
|
def set_keyframe_mode(mode: int) -> Dict[str, Any]:
|
|
519
524
|
"""Set the keyframe mode in Resolve.
|
|
520
525
|
|
|
@@ -545,6 +550,7 @@ def get_fairlight_presets() -> Dict[str, Any]:
|
|
|
545
550
|
|
|
546
551
|
|
|
547
552
|
@mcp.tool()
|
|
553
|
+
@granular_destructive_op()
|
|
548
554
|
def quit_resolve() -> Dict[str, Any]:
|
|
549
555
|
"""Quit DaVinci Resolve. WARNING: This will close the application."""
|
|
550
556
|
resolve = get_resolve()
|
|
@@ -591,6 +597,7 @@ def get_burn_in_preset_list() -> Dict[str, Any]:
|
|
|
591
597
|
|
|
592
598
|
|
|
593
599
|
@mcp.tool()
|
|
600
|
+
@granular_destructive_op()
|
|
594
601
|
def delete_burn_in_preset(preset_name: str) -> Dict[str, Any]:
|
|
595
602
|
"""Delete a data burn-in preset by name (Resolve 21.0.4+).
|
|
596
603
|
|
|
@@ -641,6 +648,7 @@ def save_user_preferences_preset(preset_name: str) -> Dict[str, Any]:
|
|
|
641
648
|
|
|
642
649
|
|
|
643
650
|
@mcp.tool()
|
|
651
|
+
@granular_destructive_op()
|
|
644
652
|
def load_user_preferences_preset(preset_name: str) -> Dict[str, Any]:
|
|
645
653
|
"""Load a user-preferences preset (Resolve 21.0.4+).
|
|
646
654
|
|
|
@@ -662,6 +670,7 @@ def load_user_preferences_preset(preset_name: str) -> Dict[str, Any]:
|
|
|
662
670
|
|
|
663
671
|
|
|
664
672
|
@mcp.tool()
|
|
673
|
+
@granular_destructive_op()
|
|
665
674
|
def delete_user_preferences_preset(preset_name: str) -> Dict[str, Any]:
|
|
666
675
|
"""Delete a user-preferences preset by name (Resolve 21.0.4+).
|
|
667
676
|
|
package/src/granular/timeline.py
CHANGED
|
@@ -105,6 +105,7 @@ def create_timeline(name: str) -> str:
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
@mcp.tool()
|
|
108
|
+
@granular_destructive_op()
|
|
108
109
|
def set_current_timeline(name: str) -> str:
|
|
109
110
|
"""Switch to a timeline by name.
|
|
110
111
|
|
|
@@ -203,6 +204,7 @@ def list_timelines_tool() -> List[str]:
|
|
|
203
204
|
|
|
204
205
|
|
|
205
206
|
@mcp.tool()
|
|
207
|
+
@granular_destructive_op()
|
|
206
208
|
def timeline_set_name(name: str) -> Dict[str, Any]:
|
|
207
209
|
"""Rename the current timeline.
|
|
208
210
|
|
|
@@ -217,6 +219,7 @@ def timeline_set_name(name: str) -> Dict[str, Any]:
|
|
|
217
219
|
|
|
218
220
|
|
|
219
221
|
@mcp.tool()
|
|
222
|
+
@granular_destructive_op()
|
|
220
223
|
def timeline_set_start_timecode(timecode: str) -> Dict[str, Any]:
|
|
221
224
|
"""Set the start timecode of the current timeline.
|
|
222
225
|
|
|
@@ -240,6 +243,7 @@ def timeline_get_current_timecode() -> Dict[str, Any]:
|
|
|
240
243
|
|
|
241
244
|
|
|
242
245
|
@mcp.tool()
|
|
246
|
+
@granular_destructive_op()
|
|
243
247
|
def timeline_set_current_timecode(timecode: str) -> Dict[str, Any]:
|
|
244
248
|
"""Set the playhead to a specific timecode.
|
|
245
249
|
|
|
@@ -288,6 +292,7 @@ def timeline_add_track(
|
|
|
288
292
|
|
|
289
293
|
|
|
290
294
|
@mcp.tool()
|
|
295
|
+
@granular_destructive_op()
|
|
291
296
|
def timeline_delete_track(track_type: str, track_index: int) -> Dict[str, Any]:
|
|
292
297
|
"""Delete a track from the timeline.
|
|
293
298
|
|
|
@@ -318,6 +323,7 @@ def timeline_get_track_sub_type(track_type: str, track_index: int) -> Dict[str,
|
|
|
318
323
|
|
|
319
324
|
|
|
320
325
|
@mcp.tool()
|
|
326
|
+
@granular_destructive_op()
|
|
321
327
|
def timeline_set_track_enable(track_type: str, track_index: int, enabled: bool) -> Dict[str, Any]:
|
|
322
328
|
"""Enable or disable a track.
|
|
323
329
|
|
|
@@ -349,6 +355,7 @@ def timeline_get_is_track_enabled(track_type: str, track_index: int) -> Dict[str
|
|
|
349
355
|
|
|
350
356
|
|
|
351
357
|
@mcp.tool()
|
|
358
|
+
@granular_destructive_op()
|
|
352
359
|
def timeline_set_track_lock(track_type: str, track_index: int, locked: bool) -> Dict[str, Any]:
|
|
353
360
|
"""Lock or unlock a track.
|
|
354
361
|
|
|
@@ -397,6 +404,7 @@ def timeline_get_voice_isolation_state(track_index: int) -> Dict[str, Any]:
|
|
|
397
404
|
|
|
398
405
|
|
|
399
406
|
@mcp.tool()
|
|
407
|
+
@granular_destructive_op()
|
|
400
408
|
def timeline_set_voice_isolation_state(track_index: int, state: Dict[str, Any]) -> Dict[str, Any]:
|
|
401
409
|
"""Set voice isolation state for an audio track.
|
|
402
410
|
|
|
@@ -415,6 +423,7 @@ def timeline_set_voice_isolation_state(track_index: int, state: Dict[str, Any])
|
|
|
415
423
|
|
|
416
424
|
|
|
417
425
|
@mcp.tool()
|
|
426
|
+
@granular_destructive_op()
|
|
418
427
|
def timeline_delete_clips(clip_ids: List[str], track_type: str = "video", track_index: int = 1) -> Dict[str, Any]:
|
|
419
428
|
"""Delete clips from the timeline.
|
|
420
429
|
|
|
@@ -437,6 +446,7 @@ def timeline_delete_clips(clip_ids: List[str], track_type: str = "video", track_
|
|
|
437
446
|
|
|
438
447
|
|
|
439
448
|
@mcp.tool()
|
|
449
|
+
@granular_destructive_op()
|
|
440
450
|
def timeline_set_clips_linked(clip_ids: List[str], linked: bool, track_type: str = "video", track_index: int = 1) -> Dict[str, Any]:
|
|
441
451
|
"""Link or unlink clips in the timeline.
|
|
442
452
|
|
|
@@ -533,6 +543,7 @@ def timeline_get_marker_custom_data(frame_id: int) -> Dict[str, Any]:
|
|
|
533
543
|
|
|
534
544
|
|
|
535
545
|
@mcp.tool()
|
|
546
|
+
@granular_destructive_op()
|
|
536
547
|
def timeline_delete_markers_by_color(color: str) -> Dict[str, Any]:
|
|
537
548
|
"""Delete all timeline markers of a specific color.
|
|
538
549
|
|
|
@@ -547,6 +558,7 @@ def timeline_delete_markers_by_color(color: str) -> Dict[str, Any]:
|
|
|
547
558
|
|
|
548
559
|
|
|
549
560
|
@mcp.tool()
|
|
561
|
+
@granular_destructive_op()
|
|
550
562
|
def timeline_delete_marker_at_frame(frame_id: int) -> Dict[str, Any]:
|
|
551
563
|
"""Delete a timeline marker at a specific frame.
|
|
552
564
|
|
|
@@ -561,6 +573,7 @@ def timeline_delete_marker_at_frame(frame_id: int) -> Dict[str, Any]:
|
|
|
561
573
|
|
|
562
574
|
|
|
563
575
|
@mcp.tool()
|
|
576
|
+
@granular_destructive_op()
|
|
564
577
|
def timeline_delete_marker_by_custom_data(custom_data: str) -> Dict[str, Any]:
|
|
565
578
|
"""Delete a timeline marker by custom data.
|
|
566
579
|
|
|
@@ -590,6 +603,7 @@ def timeline_get_track_name(track_type: str, track_index: int) -> Dict[str, Any]
|
|
|
590
603
|
|
|
591
604
|
|
|
592
605
|
@mcp.tool()
|
|
606
|
+
@granular_destructive_op()
|
|
593
607
|
def timeline_set_track_name(track_type: str, track_index: int, name: str) -> Dict[str, Any]:
|
|
594
608
|
"""Set the name of a track.
|
|
595
609
|
|
|
@@ -882,6 +896,7 @@ def timeline_create_subtitles_from_audio(
|
|
|
882
896
|
# the timeline by adding cuts. The compound server rates timeline_ai.detect_scene_cuts
|
|
883
897
|
# destructive; this is the same Resolve call, so it carries the same hint.
|
|
884
898
|
@mcp.tool(annotations=DESTRUCTIVE_TOOL)
|
|
899
|
+
@granular_destructive_op()
|
|
885
900
|
def timeline_detect_scene_cuts() -> Dict[str, Any]:
|
|
886
901
|
"""Detect scene cuts in the current timeline. DESTRUCTIVE — adds cuts to the timeline."""
|
|
887
902
|
_, tl, err = _get_timeline()
|
|
@@ -987,6 +1002,7 @@ def timeline_get_mark_in_out() -> Dict[str, Any]:
|
|
|
987
1002
|
|
|
988
1003
|
|
|
989
1004
|
@mcp.tool()
|
|
1005
|
+
@granular_destructive_op()
|
|
990
1006
|
def timeline_set_mark_in_out(mark_in: int, mark_out: int) -> Dict[str, Any]:
|
|
991
1007
|
"""Set mark in/out points for the current timeline.
|
|
992
1008
|
|
|
@@ -1002,6 +1018,7 @@ def timeline_set_mark_in_out(mark_in: int, mark_out: int) -> Dict[str, Any]:
|
|
|
1002
1018
|
|
|
1003
1019
|
|
|
1004
1020
|
@mcp.tool()
|
|
1021
|
+
@granular_destructive_op()
|
|
1005
1022
|
def timeline_clear_mark_in_out() -> Dict[str, Any]:
|
|
1006
1023
|
"""Clear mark in/out points for the current timeline."""
|
|
1007
1024
|
_, tl, err = _get_timeline()
|
|
@@ -1084,6 +1101,7 @@ def create_timeline_from_clips(
|
|
|
1084
1101
|
|
|
1085
1102
|
|
|
1086
1103
|
@mcp.tool()
|
|
1104
|
+
@granular_destructive_op()
|
|
1087
1105
|
def set_timeline_setting(setting_name: str, setting_value: str) -> Dict[str, Any]:
|
|
1088
1106
|
"""Set a timeline setting value.
|
|
1089
1107
|
|