Skip to main content
Glama

FCPXML MCP

The bridge between Final Cut Pro and AI. 13 grouped tools (88 underlying operations) that turn timeline XML into structured data Claude can read, edit, generate, SEE, find — and undo.

CI License: MIT Python 3.10+ MCP Compatible Final Cut Pro PyPI MCP Marketplace

Hardened for real libraries: 182 adversarial-input security tests, defusedxml everywhere, sandboxed writes, no patched binaries, no private APIs — plus a private disclosure channel with externally reported fixes already credited and merged.

FCPXML MCP demo: an edl.json cut into a Final Cut timeline, dead air detected in the source audio and trimmed, then rendered to a proxy

Real v0.21.2 output, start to finish: three shots cut into a timeline from an edl.json, analysed, drawn as an ASCII timeline, probed for dead air in the source audio, trimmed, redrawn, and rendered to a proxy whose duration is read back off the artifact. Recorded from demo/demo.py with vhs — every line is output from the same handlers an MCP client calls, so the GIF cannot drift from the code. Re-record it with vhs demo/demo.tape; the media is synthesised by ffmpeg at run time, so there is no fixture to keep.


Why This Exists

After a decade directing music videos (Chief Keef, Migos, Masicka), I noticed the same editing bottlenecks on every project: counting cuts manually, extracting chapter markers one by one, hunting flash frames by scrubbing, building rough cuts clip by clip.

These are batch operations that don't need visual feedback. Export the XML, let Claude handle the tedium, import the result. That's the entire philosophy.


Related MCP server: fcp-mcp

See It In Action

You:    "Run a health check on my wedding edit"

Claude: ✓ Analyzed WeddingFinal.fcpxml
        ├─ 247 clips · 42:18 total · 24fps · 1920×1080
        ├─ 3 flash frames detected (clips 44, 112, 198)
        ├─ 2 unintentional gaps at 12:04 and 31:47
        ├─ 14 duplicate source clips
        └─ Health score: 72/100

You:    "Fix the flash frames and gaps, then add chapter markers from
         this transcript"

Claude: ✓ Extended adjacent clips to cover 3 flash frames
        ✓ Filled 2 gaps by extending previous clips
        ✓ Added 18 chapter markers from transcript
        → Saved: WeddingFinal_modified.fcpxml

Import the modified XML back into Final Cut Pro. Every change is non-destructive — your original file is never touched.


What Claude Actually Sees

This is the magic trick. When you export XML from Final Cut Pro, your timeline becomes structured data that Claude can reason about:

<!-- What FCP exports -->
<asset-clip ref="r2" offset="342/24s" name="Interview_A"
            start="120s" duration="720/24s" format="r1">
    <marker start="48/24s" duration="1/24s" value="Key quote"/>
    <keyword start="0s" duration="720/24s" value="Interview"/>
</asset-clip>
# What Claude works with (after parsing)
Clip(
    name="Interview_A",
    offset=TimeValue(342, 24),   # timeline position: 14.25s
    start=TimeValue(120, 1),     # source in-point: 2:00
    duration=TimeValue(720, 24), # 30 seconds
    markers=[Marker(value="Key quote", start=TimeValue(48, 24))],
    keywords=["Interview"]
)

Every time value stays as a rational fraction — 720/24s, not 30.0 — so trim, split, and speed operations have zero rounding error across any frame rate, including the NTSC-fractional ones. A broadcast rate is carried as the exact rational it is (23.976 is 24000/1001, not a decimal), never as a truncated integer. Comparisons use cross-multiplication (a/b < c/da*d < c*b) to stay in integer-land end to end. Denominators are always normalized to positive values at construction, so sign lives on the numerator and cross-multiplication is always correct. Addition and subtraction share a single _binop() code path that handles same-denominator fast paths and LCM alignment in one place.


How It Works

  ┌──────────┐      ┌──────────────────────────────┐      ┌──────────┐
  │ Final Cut│      │  parser.py   → Python objects │      │ Final Cut│
  │   Pro    │─XML─>│  writer.py   → Modify & save  │─XML─>│   Pro    │
  │          │      │  rough_cut.py→ Generate new   │      │          │
  └──────────┘      │  diff.py     → Compare        │      └──────────┘
                    │  export.py   → Resolve / FCP7 │
                    └──────────────────────────────┘
                              ▲
                     Claude Desktop / MCP client
  1. Export from FCPFile → Export XML...

  2. Ask Claude — analyze, edit, generate, QC, export

  3. Import backFile → Import → XML

What This Is NOT

  • Not a plugin — it doesn't run inside Final Cut Pro

  • Not for creative calls — color, framing, motion still need your eyes

New in v0.9 — Live Mode. The server can now push an FCPXML straight into the running Final Cut Pro with zero clicks, using Apple's official Open Document event — no XML re-import step. See Live Mode below.


Live Mode (macOS)

XML mode is offline and portable; Live mode drives a running Final Cut Pro through Apple's sanctioned surfaces — no patched binary, no private APIs, no accessibility scripting. Two tools, both verified end-to-end against FCP 12.2:

Tool

What it does

push_to_fcp

Sends an FCPXML file into FCP with zero clicks (Open Document Apple event). Injects <import-options> (library location, copy/link assets, suppress warnings), launches FCP if needed, and never mutates your original — flat files get an options-injected copy.

list_fcp_libraries

Enumerates FCP's open libraries → events → projects via the read-only AppleScript dictionary.

You:    "Build a rough cut from my Interview clips and push it into Final Cut"

Claude: ✓ Generated RoughCut.fcpxml (8 clips, 0:54)
        ✓ Pushed into Final Cut Pro → library "ProjectX", event 2026-06-11
        → Open Final Cut Pro to keep editing

The asymmetry you must know: Apple makes import scriptable but offers no programmatic export — to pull your current timeline back out for further AI work, you still run File > Export XML yourself. Live mode pushes; round-trips come back through the XML tools.

Notes (all live-verified): pass a library_location ending in .fcpbundle for a true zero-click import (a new path is auto-created); omitting it makes FCP show a modal library picker that blocks until you answer. First use triggers a one-time macOS Automation permission prompt for your terminal/MCP host. The capability audit maps the full surface and the optional SpliceKit/CommandPost bridges planned for v1.0.


The Round Trip

Final Cut Pro has a fully scriptable import and no programmatic export — verified unchanged across FCP 11.0 → 12.2. So the loop closes on exactly one keystroke, and everything either side of it is automated:

watch_start                    ← once per session (or set FCP_WATCH_DIR)
   ↓
edit / generate / mark         ← the change
   ↓
preview_check                  ← SEE it. Reads the media, not the XML
   ↓
deliver.push_to_fcp            ← zero-click import (or FCP_MCP_AUTOPUSH=1)
   ↓
Cmd-E in Final Cut Pro         ← the one manual step Apple leaves you
   ↓
watch_pull                     ← detected and diffed against the last export

preview_check is the part that matters. The preview:// resource and preview_timeline both draw from the XML — they show what was written, so a fixed flash frame and a broken one read identically through them. preview_check samples the source media into a filmstrip over an audio waveform. It is the difference between a tool reporting success and you knowing the cut is right.

If you have SpliceKit or CommandPost installed, watch_start says so. This server does not call either one — their RPC signatures have not been verified against a live install, and it never patches or injects anything. That is why it runs on a managed Mac and survives an FCP update.


Quick Start

Claude Code (fastest)

claude mcp add fcpxml -e FCP_PROJECTS_DIR=~/Movies -- uvx fcp-mcp-server

Or project-scoped — commit a .mcp.json so your whole team gets it:

{
  "mcpServers": {
    "fcpxml": {
      "command": "uvx",
      "args": ["fcp-mcp-server"],
      "env": { "FCP_PROJECTS_DIR": "/Users/you/Movies" }
    }
  }
}

With media intelligence (beat detection) and transcript editing (local Whisper):

claude mcp add fcpxml -e FCP_PROJECTS_DIR=~/Movies -- uvx --from "fcp-mcp-server[intelligence,transcribe]" fcp-mcp-server

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "fcpxml": {
      "command": "uvx",
      "args": ["fcp-mcp-server"],
      "env": { "FCP_PROJECTS_DIR": "/Users/you/Movies" }
    }
  }
}

From source (contributors)

git clone https://github.com/DareDev256/fcp-mcp-server.git
cd fcp-mcp-server
pip install -e .
# then point your MCP client at: python /path/to/fcp-mcp-server/server.py

Use It

Export XML from Final Cut Pro (File → Export XML…), open your MCP client, and ask it to work with your timeline.


When To Use This

Good For

Not Ideal For

Batch marker insertion (100 chapters from a transcript)

Fine-tuning cuts (faster directly in FCP)

QC before delivery (flash frames, gaps, duplicates)

Colour, framing and motion (nothing here grades)

Data extraction (EDL, CSV, chapter markers)

Sound mixing beyond stems and role splits

Template generation (rough cuts from tagged clips)

Anything needing a scrub through the actual cut

Automated assembly (montages from keywords + pacing)

Timeline health checks (validation, stats, scoring)

Logging and search before the edit (scenes, transcript, shot search)


How It Compares

Three projects have connected AI agents to Final Cut Pro. They make different trade-offs:

FCPXML MCP (this)

SpliceKit

CommandPost

Approach

Parses/writes FCPXML + official Apple events only

Patches FCP's binary to expose internal APIs

Accessibility scripting + Lua

Raw live control

Push-to-FCP, library inspection

Deepest (full internal API)

Deep (UI-level)

Survives FCP updates

Yes — no patching

Re-patch per FCP version

Mostly

Works on managed/corporate Macs

Yes

No (requires binary patching)

Varies (Accessibility perms)

Works without FCP installed

Yes (pure XML mode)

No

No

MCP server

Yes, active (this repo)

Yes (last release Apr 2026)

Planned, PR unmerged

Requires

Python 3.10+

Patched FCP binary

CommandPost app

SpliceKit's runtime depth is genuinely impressive — if you're on your own Mac and comfortable patching FCP, it can do things XML never will. This project stays on the no-patch side so it runs anywhere, survives every FCP update, and can be trusted with client libraries. Full ecosystem analysis: capability audit.


Prompt Cookbook

Copy-paste these into Claude Desktop. Each one maps to a real tool chain under the hood.

Analysis

"Give me a full breakdown of ProjectX.fcpxml — clips, duration, frame rate, markers, everything"
"Show me pacing analysis for my timeline — where are the slow sections?"
"Export an EDL and CSV of all clips with timecodes"

QC & Fixes

"Run a health check on my timeline and fix anything under 2 frames"
"Find all gaps and flash frames, then auto-fix them"
"Are there any duplicate source clips I can consolidate?"

Markers & Chapters

"Add chapter markers from this transcript: [paste transcript]"
"Import markers from my-subtitles.srt onto the timeline"
"List all markers and export them as YouTube chapter timestamps"

Generation

"Build a 60-second rough cut from clips tagged 'Interview' — medium pacing"
"Generate a montage from all B-roll clips with accelerating pacing"
"Create an A/B roll: Interview_A as primary, B-roll cuts every 8 seconds"

Cross-NLE & Reformat

"Export this timeline for DaVinci Resolve"
"Convert to FCP7 XML so I can open it in Premiere"
"Reformat my 16:9 timeline to 9:16 for Instagram Reels"

Under the Hood

When you say "Run a health check on my wedding edit", Claude chains these tools:

analyze_timeline  →  stats, frame rate, resolution
detect_flash_frames  →  clips under threshold duration
detect_gaps  →  unintentional silence/black
detect_duplicates  →  repeated source media
validate_timeline  →  structural health score (0-100)

Each tool returns structured text that Claude synthesizes into the summary you see. No magic — just batch XML queries that would take 20 minutes by hand.

Music videos and connected clips

A music video is usually built by laying an audio bed and hanging every visual off it as a connected clip, so the spine holds one <gap> and the entire edit lives on lanes. snap_to_beats and detect_flash_frames work on that shape: snapping runs lane by lane, does not ripple the clips after the one it moves, skips (and names) any move that would collide with a neighbour in the same lane, and leaves the audio bed alone unless you pass include_audio_lanes. It reports cuts considered, moved, already on a beat, out of reach, and skipped — so "nothing moved" is something you are told rather than something you discover in Final Cut.

reorder_clips, rapid_trim, fix_flash_frames and fill_gaps are still primary-storyline only.


Pre-Built Prompts

Select these from Claude's prompt menu (⌘/) — they chain multiple tools automatically.

Prompt

What It Does

Grouped calls it drives

qc-check

Full quality control — flash frames, gaps, duplicates, health score

diagnosevalidate_timeline, detect_flash_frames, detect_gaps, detect_duplicates; then editfix_flash_frames, fill_gaps

youtube-chapters

Extract chapter markers formatted for YouTube descriptions

inspectlist_markers, analyze_pacing

rough-cut

Guided rough cut — shows clips, suggests structure, generates

inspectlist_library_clips, list_keywords; then generateauto_rough_cut

timeline-summary

Quick overview — stats, pacing, keywords, markers, assessment

inspectanalyze_timeline, analyze_pacing, list_keywords, list_markers

cleanup

Find and auto-fix flash frames and gaps

diagnosevalidate_timeline; then editfix_flash_frames, fill_gaps

Every call takes the grouped form — the tool name is the group, and the operation goes in action:

{ "action": "validate_timeline", "args": { "filepath": "/path/to/project.fcpxml" } }

Tools

As of v0.19.0, the MCP tool list Claude sees by default is 13 grouped verbs, not 88 flat tool names:

Group

Covers

inspect

Read-only understanding — stats, clips, markers, keywords, EDL/CSV, pacing

diagnose

Finding problems — flash frames, gaps, duplicates, health score

edit

Changing clips — markers, trim, reorder, transitions, speed, split, silence removal

mark

Markers and chapters — batch add, SRT/VTT import, beat import

generate

Building new structure — rough cuts, montages, A/B roll, templates

transcript

Local Whisper transcription and transcript-driven cuts; transcript_pack puts the whole shoot on one page; backend: elevenlabs opts into speaker labels and audio events (audio leaves the machine)

deliver

Getting the timeline out — NLE export, reformat, relink, push-to-FCP

preview

Seeing the edit — ffmpeg proxy render, contact sheet, and a filmstrip+waveform check read from the SOURCE MEDIA

watch

Closing the round-trip — notice the operator's Cmd-E export and diff it against the last one

index

The analysis cache — status with its age, warm every source in a timeline, clear. Nothing depends on it; FCP_MCP_INDEX=off and every tool still answers, only slower

scenes

Shot boundaries from the pixels — list cuts per clip in source and timeline time, drop a marker on each, or split the clips there. PySceneDetect when installed, ffmpeg otherwise

organize

Library housekeeping — bulk keywords, ratings and roles over a clip selection; organize_auto proposes keywords from captions and transcripts; history reads the operation ledger and undo moves the last outputs aside (never deletes)

find

"Find the shot where…" — a router over transcript words, metadata and offline vision captions that names the tier on every hit; find_index warms every source; find_to_timeline assembles the hits into a selects reel

Each call has the same shape: {"action": "trim_clip", "args": {...}}. The action is one of the 88 operation names below; args is whatever that tool always took. The group dispatches straight into the same handler — the behavior is identical, only the schema Claude sees up front is smaller. An unknown or cross-group action returns an error listing the valid actions for that group, so a wrong guess is recoverable in one turn.

Grouping is what's advertised, not what's callable. call_tool resolves every one of the 88 operation names from a handler registry that doesn't care what list_tools chose to show — an existing MCP config that calls trim_clip directly keeps working with no changes. If you'd rather also see the flat tool schemas (e.g. for debugging, or a client that doesn't like the grouped shape), set:

FCP_MCP_LEGACY_TOOLS=1

This advertises the 63 flat schemas alongside the 13 groups — 76 tools in total. The 25 operations that were born as group actions (preview, watch, index, scenes, organize, find, plus import_edl_json) have no flat schema and are reached through their group. The flat tools will not be removed before a 1.0 release.

See the timeline before you touch it

Reading the preview://<path> MCP resource (any FCPXML path the server can already reach) returns a self-contained HTML render of the timeline: clip blocks sized proportionally to duration, connected clips on their own lane rows above/below the primary storyline, and marker ticks — all values HTML-escaped, served as text/html. Point your MCP client's resource viewer at it, or fetch it directly, to see a cut without opening Final Cut Pro.

Timeline preview: 129 clips across 15 lanes rendered as coloured blocks, with the music bed on lane -1 and colour-grade layers on lanes 9 to 14

A real 164-second music video: 129 connected clips across 15 lanes, rendered from its FCPXML alone. Clip names on reference layers have been relabelled.

Claude Code skill

A final-cut-pro skill ships in skill/, wrapping this server with the workflow order (inspectdiagnose → read preview://edit) and the FCPXML gotchas that don't fit in a tool description. Install it alongside the MCP server:

git clone https://github.com/DareDev256/fcp-mcp-server
ln -s "$PWD/fcp-mcp-server/skill" ~/.claude/skills/final-cut-pro

All 88 Operations

The 88 operations below are what the 13 groups in Tools dispatch to — every action value the groups accept. The first 63 are unchanged from prior releases and still callable directly with FCP_MCP_LEGACY_TOOLS=1.

Category

Tools

What It Does

Analysis

11

Stats, clips, markers, keywords, EDL/CSV, pacing

Multi-Track

3

Connected clips, compound clips, secondary lanes

Roles

4

List, assign, filter, export stems

QC & Validation

4

Flash frames, duplicates, gaps, health score

Editing

9

Markers, trim, reorder, transitions, speed, split

Batch Fixes

3

Auto-fix flash frames, rapid trim, fill gaps

Comparison

1

Diff two timelines — added/removed/moved/trimmed

Reformat

1

Aspect ratio conversion (9:16, 1:1, 4:5, custom)

Silence

2

Detect and remove silence candidates (XML heuristics)

Media Intelligence

3

Real silence detection + auto-removal (ffmpeg), musical beat detection (librosa)

NLE Export

2

DaVinci Resolve v1.9, FCP7 XMEML v5

Generation

3

Rough cuts, montages, A/B roll

Beat Sync

2

Import beat markers, snap cuts to beats

Import

3

SRT/VTT subtitles, YouTube chapters → markers; video-use edl.json → FCPXML

Audio

1

Add audio clips, music beds at any lane

Compound

2

Create/flatten compound clips

Templates

2

Pre-built timeline structures (intro/outro, lower thirds, music video)

Effects

1

List FCP transition effects with UUIDs

Media

1

Bulk relink moved/renamed media (rewrite media-rep src paths)

Transcript Intelligence

4

Local Whisper transcription, transcript-driven cuts, filler-word removal, the one-page transcript pack

Live (macOS)

2

Push FCPXML into the running FCP (zero-click Apple-event import); list open libraries

Preview

5

Proxy render, contact sheet, single frame, filmstrip+waveform check from the source media, HTML timeline

Watch

4

Start/status/stop an export watch folder; pull the latest export and diff it

Index

3

Analysis cache status (with age), build, clear

Scenes

3

Detect shot boundaries, mark them, split on them

Organize

6

Bulk keywords/ratings/roles, auto-proposed keywords, operation history, hash-checked undo

Find

3

Shot search across transcript, metadata and vision tiers; warm the index; assemble a selects reel

88

Analysis — 11 tools

list_projects · analyze_timeline · list_clips · list_library_clips · list_markers · find_short_cuts · find_long_clips · list_keywords · export_edl · export_csv · analyze_pacing

Multi-Track — 3 tools

list_connected_clips · add_connected_clip · list_compound_clips

Roles — 4 tools

list_roles · assign_role · filter_by_role · export_role_stems

QC & Validation — 4 tools

detect_flash_frames · detect_duplicates · detect_gaps · validate_timeline

Editing — 9 tools

add_marker · batch_add_markers · insert_clip · trim_clip · reorder_clips · add_transition · change_speed · delete_clips · split_clip

Batch Fixes — 3 tools

fix_flash_frames · rapid_trim · fill_gaps

Comparison · Reformat · Silence

diff_timelines · reformat_timeline · detect_silence_candidates · remove_silence_candidates

NLE Export — 2 tools

export_resolve_xml (DaVinci Resolve FCPXML v1.9) · export_fcp7_xml (Premiere Pro / Resolve / Avid XMEML v5)

Generation — 3 tools

auto_rough_cut · generate_montage · generate_ab_roll

Beat Sync — 2 tools

import_beat_markers · snap_to_beats

Import — 3 tools

import_srt_markers · import_transcript_markers (supports SMPTE HH:MM:SS:FF with frame-accurate placement) · import_edl_json (video-use {sources, ranges, grade?} → FCPXML; ranges[].source is a key into sources, not a path — v0.17.0)

v0.6.0 — Audio, Compound, Templates, Effects — 6 tools

list_effects · add_audio · create_compound_clip · flatten_compound_clip · list_templates · apply_template

v0.8.0 — Media — 1 tool

relink_media (bulk-rewrite asset/media-rep src paths with dry_run preview — relink a moved drive without opening FCP)

v0.10–0.12 — Media Intelligence — 3 tools

detect_media_silence (analyzes each clip's real source audio with ffmpeg silencedetect and maps silence spans into timeline time) · remove_media_silence (cuts detected silence out of the timeline with ripple — clips split around silence, padding keeps edits breathing, non-destructive output) — both require ffmpeg, degrade gracefully without it · detect_beats (musical beat + tempo detection via librosa, writes a beats JSON that chains into import_beat_markers + snap_to_beats; needs the optional [intelligence] extra)

v0.13.0 / v0.18.0 — Transcript Intelligence — 4 tools

transcribe_media · edit_by_transcript · remove_filler_words · transcript_pack (v0.18.0 — one page of everything said; every one of the four takes backend: "elevenlabs" for speakers and audio events)

v0.9.0 — Live Mode (macOS + Final Cut Pro) — 2 tools

push_to_fcp (zero-click FCPXML import into the running FCP via Apple event) · list_fcp_libraries (enumerate open libraries/events/projects)

v0.17.0 — Preview — 5 group actions

preview_render · preview_sheet · preview_frame · preview_check · preview_timeline

Since v0.20.0 preview_render compiles crossfades and video lanes rather than flattening them: a transition on a cut becomes an ffmpeg xfade (dissolve, dip to colour, wipe, slide), and a connected clip is overlaid for its own window, shifted by any crossfade that shortened the timeline before it. What the renderer cannot honour is printed with the render — a transition with no cut within its own duration, one whose neighbour is missing its media, a lane drawn full-frame because transforms and opacity are not read, and audio lanes, which are never mixed. The reported duration accounts for the overlaps, and preview_render reads the artifact's own duration back against it.

v0.17.0 — Watch — 4 group actions

watch_start · watch_status · watch_stop · watch_pull

v0.18.0 — Index — 3 group actions

index_status · index_build · index_clear

v0.18.0 — Scenes — 3 group actions

detect_scenes · scenes_to_markers · scenes_split

v0.19.0 — Organize — 6 group actions

organize_keywords (add / remove / replace over a selection by glob name, keyword or role) · organize_rate (favorite / rejected / clear) · organize_roles · organize_auto (proposes keywords from cached captions and transcripts; never transcribes; apply=true writes) · history (the operation ledger as a table with ages) · undo (moves the last N recorded outputs to <journal>/undone/ — never deletes, refuses on hash mismatch)

v0.19.0 — Find — 3 group actions

find_shots (tiered router — transcript, metadata, vision — with the tier and a why on every hit; at most 20 live captions per call) · find_index (warm transcripts, scenes and opt-in captions for every source, reporting each as done / skipped / unavailable) · find_to_timeline (assemble the hits into a _found selects reel under the diversity constraint)


Environment Variables

Variable

Required

Default

Description

FCP_PROJECTS_DIR

No

~/Movies

Root directory for FCPXML discovery via list_projects. Confines listing only — it does not restrict which files you can open

FCP_PROJECTS_DIRS

No

unset

Sandbox roots, separated like PATH (: on macOS/Linux) — e.g. ~/Movies:/Volumes/Scratch/Projects. This is the only variable that confines reads, and it is fully opt-in. Symlinked library media (Final Cut's default "leave files in place" import) stays readable

FCP_MAX_DISCOVERY_FILES

No

10000

Cap on files collected by one list_projects directory walk. The walk stops at the cap and the result says it is incomplete

FCP_MAX_BATCH_MARKERS

No

10000

Cap on markers written by one batch or import operation. Excess markers are reported as dropped, never silently skipped

FCP_MAX_TRANSCRIPT_CHARS

No

1048576

Cap on inline transcript text passed to import_transcript_markers

FCPXML_DTD_DIR

No

FCP app bundle

Directory of Apple FCPXMLv*_*.dtd files for DTD validation (auto-detected from the installed Final Cut Pro)

FCP_MCP_LEGACY_TOOLS

No

unset

Set to 1 to advertise the 63 flat tool schemas alongside the 13 grouped tools

FCP_WATCH_DIR

No

unset

Default folder watch_start observes for Final Cut Pro XML exports

FCP_MCP_AUTOPUSH

No

unset

Set to 1 so every write also imports into the running Final Cut Pro. Off by default — repeated imports accumulate library churn, which is your call to make

FCP_MCP_INDEX

No

~/.fcp-mcp/index.db

Where the analysis cache lives. off disables it entirely; every tool still works, it just recomputes. Any other value is a path

ELEVENLABS_API_KEY

No

unset

Enables backend: "elevenlabs" on the transcript tools. Sent as the xi-api-key header and nowhere else; never read unless that backend is requested

FCP_MCP_JOURNAL

No

~/.fcp-mcp/journal/

Where the operation ledger lives (paths and hashes, never content). off disables it — history/undo then say so and the deliver review gate refuses to certify anything

FCP_MCP_VLM_MODEL

No

mlx-community/Qwen2-VL-2B-Instruct-4bit

Hub id of the MLX vision model find captions shots with. Loaded offline only; a missing model is reported with its hf download command, never fetched


Compatibility

Component

Supported Versions

FCPXML format

reads v1.8 – v1.14 · writes v1.13 (modified files keep their source version)

Final Cut Pro

10.4+ through 12.x · flat .fcpxml and .fcpxmld bundles (sidecars preserved)

Python

3.10, 3.11, 3.12

MCP protocol

1.0

mcp SDK

1.3.0 through 2.x — both the decorator API and the add_request_handler API that replaced it. CI tests the declared floor and 2.x on every push

Export targets

→ DaVinci Resolve

FCPXML v1.9

→ Premiere Pro / Avid

FCP7 XMEML v5


Architecture

fcp-mcp-server/           ~15.7k lines Python
├── server.py              MCP entry point — 13 grouped tools advertised by default
│                          (TOOL_GROUPS), dispatching into 88 handlers
│                          (TOOL_HANDLERS); 5 prompts, resource discovery.
│                          FCP_MCP_LEGACY_TOOLS=1 re-advertises the flat tools.
│                          Binds itself to tools/ via bind_server() — group modules
│                          must never `import server` (it runs as __main__).
├── tools/                 New tool groups, registered without growing server.py
│   ├── __init__.py        EXTRA_GROUPS/EXTRA_HANDLERS registry + bind_server()
│   ├── _common.py         text_result / parse_project through the bound module
│   ├── preview.py         preview group — render, sheet, frame, check, timeline
│   ├── watch.py           watch group — start, status, stop, pull
│   ├── index.py           index group — status (with age), build, clear
│   ├── scenes.py          scenes group — detect, to_markers, split
│   ├── organize.py        organize group — keywords, rate, roles, auto, history, undo
│   ├── find.py            find group — shots (tiered router), index, to_timeline
│   └── nle.py             NLE export, effects, audio, compound clips, templates,
│                           relink — moved out of server.py, re-exported by it
│                          _resolve_io_paths() / _setup_modifier() / _setup_generator()
│                          _format_clip_table() / _markdown_table() / _format_batch_result()
│                          _raw_markers_to_batch()
│                          _detect_flash_frames() / _detect_gaps() / _detect_duplicate_groups()
│                          consolidate path validation, QC detection, rendering, handler boilerplate
├── fcpxml/
│   ├── journal.py         Append-only operation ledger — paths + hashes, never content;
│   │                       undo is a pointer move into undone/, refused on hash mismatch
│   ├── find.py            Pure ranking over transcript words and metadata ranges, tier named
│   ├── vlm.py             Offline MLX shot captions — HF offline flags set BEFORE import.
│   │                       Captions a 1080p frame: vision tokens scale with pixel area
│   ├── diversity.py       Source-separation constraint + diversity score for assemblies
│   ├── index.py           SQLite analysis cache — keyed (path, mtime, size), num/den time,
│   │                       rebuilt on corruption; NEVER a source of truth (CI runs it off)
│   ├── progress.py        Per-clip MCP progress notifications on either SDK
│   ├── scenes.py          Shot boundaries — PySceneDetect or ffmpeg's coarser scene filter
│   ├── transcript_pack.py Every transcript on one page; byte-measured 60KB cap
│   ├── transcribe.py      Local faster-whisper, or ElevenLabs Scribe opt-in (speakers, events)
│   ├── filtergraph.py     Timeline → ffmpeg graph. PURE — Fraction end to end,
│   │                       so compilation is asserted without ffmpeg installed.
│   │                       xfade crossfades + full-frame lane overlays; what it
│   │                       cannot honour is reported, never silently dropped
│   ├── render.py          Executes the graph; probes the artifact's OWN duration
│   │                       back and reports drift against the timeline rational
│   ├── visual.py          Filmstrip + waveform from SOURCE MEDIA (preview_check)
│   ├── watchfolder.py     Export detection. Digests CONTENT, not (mtime, size)
│   ├── bridges.py         SpliceKit :9876 / CommandPost :27480 — DETECTION ONLY
│   ├── edl.py             video-use edl.json → FCPXML
│   ├── models.py          TimeValue, Timecode, Clip, ConnectedClip, MarkerType, Timeline
│   ├── parser.py          FCPXML → Python (spine, connected clips, roles, markers)
│   ├── writer.py          Modify & write (markers, trim, gaps, transitions, silence)
│   │                       FCPXMLModifier: index-based editing (clips/resources/formats dicts)
│   │                       FCPXMLWriter: generate new FCPXML from Python objects
│   │                       Helpers: _resolve_asset, _absorb_into_neighbor, _ripple_from_index
│   ├── rough_cut.py       Generate timelines (rough cuts, montages, A/B roll)
│   ├── diff.py            Timeline comparison engine (identity matching, threshold docs)
│   ├── export.py          DaVinci Resolve v1.9 + FCP7 XMEML v5 export
│   ├── media_intel.py     Real media analysis — audio silence detection via bounded ffmpeg subprocess
│   ├── preview.py         Standalone HTML timeline render, served as preview://<path>
│   ├── safe_xml.py        Centralized defusedxml wrappers (XXE/entity-bomb protection) + serialize_xml()
│   ├── dtd.py             Validate output against Apple's official DTDs (located in the FCP app bundle)
│   └── templates.py       Template system (intro/outro, lower thirds, music video)
├── skill/                 final-cut-pro Claude Code skill wrapping this server
├── tests/                 1753 tests across 66 suites — see Testing below
│   ├── test_models.py     TimeValue math, Timecode formatting, MarkerType contracts
│   ├── test_parser.py     FCPXML parsing, connected clips, edge cases
│   ├── test_writer.py     Clip editing, marker writing, speed changes
│   ├── test_fcpxml_writer.py  FCPXMLWriter generation from Python objects
│   ├── test_server.py     MCP tool handlers, dispatch, path validation
│   ├── test_rough_cut.py  Rough cut generation, montage, A/B roll
│   ├── test_diff.py       Moved clips, transitions, markers, clip identity
│   ├── test_export.py     Attribute stripping, compound flattening, audio tracks
│   ├── test_features_v05.py  Multi-track, roles, diff, reformat, export
│   ├── test_features_v06.py  Audio, compound clips, templates, effects, validation
│   ├── test_marker_pipeline.py  Marker builder, batch modes, output format
│   ├── test_speed_cutting.py  Speed cutting, montage config, pacing curves
│   ├── test_security.py   Input validation, XML sanitization, XXE protection
│   ├── test_edge_cases.py Boundary arithmetic, clip collisions, split/diff edges
│   ├── test_diversity.py  Boundary conditions across diff, models, validation
│   ├── test_refactored_helpers.py  _index_elements, _iter_spine_clips, serialize_xml edges
│   ├── test_targeted_gaps.py  Targeted branch coverage for diff, export, models
│   ├── test_bundles.py    .fcpxmld bundles, sidecar preservation, FCPXML 1.13/1.14 tolerance
│   ├── test_relink.py     Bulk media relink (URL + plain paths, dry run, segment matching)
│   ├── test_media_intel.py  silencedetect parsing, timeline mapping, real-WAV integration, handler
│   ├── test_transcribe.py Phrase/filler span matching, range merge/invert algebra, Whisper handlers
│   ├── test_validation.py Pydantic input validation models
│   ├── test_live.py       push_to_fcp / list_fcp_libraries (Apple events, mocked + live-gated)
│   ├── test_tool_groups.py  TOOL_GROUPS dispatch to the TOOL_HANDLERS, legacy flag, schema size
│   ├── test_index*.py     The cache: invalidation, rebuild, wiring, and the index group
│   ├── test_scenes*.py    Shot boundaries on synthesised colour bars; the scenes group
│   ├── test_transcript_pack*.py  The one-page pack and its handler
│   ├── test_transcribe_scribe.py  Scribe backend with urlopen patched; key-leak mutation check
│   ├── test_preview.py    preview:// HTML timeline render
│   ├── test_skill.py      final-cut-pro skill structure
│   └── test_dtd_validation.py  Output validated against Apple's shipped DTDs (skips without FCP)
├── docs/
│   ├── WORKFLOWS.md       8 production workflow recipes
│   └── CAPABILITY-AUDIT-2026-06.md  Ecosystem audit + dual-mode (XML + Live) roadmap
└── examples/
    └── sample.fcpxml      9 clips, 24fps — test fixture

Security

Every tool handler is hardened against adversarial input — critical for MCP servers where prompts may be LLM-generated, not human-typed.

Found a vulnerability? Report it privately via the repo's Security → Report a vulnerability tab — see SECURITY.md.

Layer

Protection

File I/O

Path traversal blocked, null bytes rejected, symlinks resolved, 100 MB size limit

Output sandbox

All generation, write, export, beat sync, subtitle, and reformat handlers enforce _validate_output_path(anchor_dir=...) — restricts writes to descendants of the source file's directory, blocking LLM-generated path escapes

Subprocess bounds

_ensure_video_asset() bounds-checks duration (0 < d ≤ 3600s), fps (1–240), width/height (even, ≤ 7680×4320) before subprocess.run() — blocks inf/NaN, negative values, odd dimensions, string injection, and oversized resolutions that could hang or exhaust ffmpeg

Speed validation

handle_change_speed validates speed is positive and ≤100 before any math — prevents ZeroDivisionError crash and nonsensical results

Sandbox roots

Opt-in and off by default — an editor's projects live wherever the user keeps them. FCP_PROJECTS_DIRS (several roots, PATH-separated) turns on read confinement: _validate_filepath rejects any path that is neither inside a root as given nor resolves into one. FCP_PROJECTS_DIR is unchanged from 0.15.0 — it confines listing only and never restricts reads, so an existing install is unaffected by upgrading. Traversal still normalises before the check (root/../etc is judged as /etc), and the extension whitelist still runs on the resolved suffix, so innocent.fcpxml → /etc/passwd is rejected either way

Directory listing

Confined to FCP_PROJECTS_DIR when set, plus any FCP_PROJECTS_DIRS roots — unchanged behaviour. find_fcpxml_files globs *.fcpxml / *.fcpxmld under the requested directory and every path that is subsequently opened goes back through _validate_filepath; with neither variable set, the caller may name any directory to list

Resource caps

The list_projects walk stops at FCP_MAX_DISCOVERY_FILES (10,000) rather than collecting and slicing, so pointing it at / cannot walk the filesystem; marker batches and imports stop at FCP_MAX_BATCH_MARKERS (10,000); inline transcript text stops at FCP_MAX_TRANSCRIPT_CHARS (1 MB), cut on a line boundary so a timestamp is never split. Every cap returns an explicit ⚠️ TRUNCATED notice naming what was dropped — a partial result is never presented as a complete one

XML parsing

defusedxml with explicit forbid_entities/external=True blocks XXE, billion laughs, entity expansion, remote DTD attacks at all 4 entry points (parser, writer, exporter, rough cut) — minidom pretty-print path also hardened via defusedxml.minidom. Ruff S314/S320 rules enforce safe parsing in CI

JSON depth limit

Iterative BFS depth checker rejects payloads nested beyond 50 levels — immune to RecursionError even at ~1000 nesting

Symlink resolution

_validate_filepath calls Path.resolve() before the extension whitelist runs, so a symlink named innocent.fcpxml that points at /etc/passwd is rejected on its resolved suffix — a symlink cannot smuggle a disallowed target past the file gate

Marker strings

Sanitized via _sanitize_xml_value() — null bytes, control chars stripped before write

Role values

Stripped of control characters before XML attribute assignment

Resource URI parsing

file:// and preview:// URIs have their scheme removed with str.removeprefix() (leading match only, so a path containing the scheme string is not mangled) and are then urllib.parse.unquote()d before validation — so percent-encoded traversal, percent-encoded null bytes, and ordinary spaces in filenames are all decoded first and then run through the same _validate_filepath gate as every other path

Output suffixes

Path separators and special characters stripped — no traversal via suffix injection

Marker types

completed attribute strict-matched ('0'/'1' only) — rejects "true", "1 OR 1=1", whitespace-padded values

182 security-specific tests across test_security.py (pytest tests/test_security.py --collect-only -q) covering XXE, path traversal, sandbox root confinement (single and multi-root), resource caps (discovery walk, marker batch, inline transcript), output path anchoring, input validation, subprocess bounds, minidom hardening, JSON depth limits, role sanitization, ffmpeg parameter bounds, symlink resolution, resource-URI decoding, preview:// rejection paths, symlinked Final Cut library media, and write-handler sandbox enforcement. Ruff S (bandit) rules enforced in CI — S314/S320 block unsafe XML parsing, S105 catches hardcoded passwords, S108 flags insecure temp paths. Security events (null bytes, sandbox escapes, unhandled exceptions) are logged via Python logging for audit trails.


Timestamp Parsing — How Import Tools Place Markers

All subtitle and transcript import tools (import_srt_markers, import_transcript_markers) funnel through a single internal function: _parse_timestamp_parts() in server.py. Understanding it matters when timestamps don't land where you expect.

Supported Formats

Format

Example

Parts

Result

Minutes:Seconds

1:30

2

90.0s

H:MM:SS

1:05:30

3

3930.0s

HH:MM:SS.ms

00:02:15.500

3

135.5s

SMPTE (HH:MM:SS:FF)

01:00:10:12

4

3610.5s @ 24fps

The SMPTE 4-part format converts the frame component to fractional seconds: frames / frame_rate. The default rate is 24fps — pass frame_rate= to override for 25fps (PAL) or 30fps (NTSC) projects.

The Import Pipeline

SRT / VTT / YouTube chapters / plain transcript
        │
        ▼
  parse_srt()  /  parse_vtt()  /  parse_transcript_timestamps()
        │                │                      │
        └────────────────┴──────────────────────┘
                         │
                    split on ':'
                         │
                         ▼
             _parse_timestamp_parts(parts, frame_rate=24.0)
                         │
                         ▼
                   total seconds (float)
                         │
                         ▼
               marker placed on timeline

Edge Cases

  • Unrecognized part counts (1 part, 5+ parts) return None — the marker is silently skipped, not placed incorrectly

  • Zero frame rate — falls back to base seconds (frames ignored) rather than dividing by zero

  • Milliseconds — only carried in 3-part format via float() on the seconds component ("15.500"15.5)

  • Frame rounding — SMPTE frames are divided exactly (12/24 = 0.5), not rounded to the nearest frame boundary. The resulting float is converted to FCPXML's rational TimeValue downstream, preserving precision

Why This Matters

Before v0.6.20, the 4-part SMPTE parser silently dropped frames — 01:00:10:12 became 3610.0s instead of 3610.5s. At 24fps, that's up to ~0.96 seconds of drift per marker. If you imported a subtitle file with SMPTE timecodes, every marker was slightly off. This was subtle enough to pass QC but visible when scrubbing.


Design Principles

Principle

Implementation

Rational time, never floats

All durations are fractions (600/2400s) matching FCPXML's native format — zero rounding errors across trim, split, speed

Non-destructive by default

Modified files get _modified, _chapters suffixes. Originals are never overwritten

Single source of truth

MarkerType enum owns serialization: from_string() for input, from_xml_element() for parsing, xml_attrs for writing. INCOMPLETE is canonical; TODO is a backward-compat alias (same object)

Security-first

13-layer defense-in-depth across all 62 handlers — see Security for the full matrix

Dispatch, not conditionals

TOOL_HANDLERS dict maps names → async handlers. No 1000-line if/elif


Documentation

Guide

What's Inside

WORKFLOWS.md

8 production recipes — QC pipelines, beat-synced assembly, cross-NLE handoffs, documentary A/B roll

MCP_ECOSYSTEM.md

How this server composes with GitNexus, filesystem, and memory MCP servers

CHANGELOG.md

Full version history from v0.1.0 to present


Testing

uv run --extra dev pytest tests/ -v    # or: python3 -m pytest tests/ -v
ruff check . --exclude docs/           # lint — must pass before committing

1753 tests across 66 suites — 1746 pass and 7 skip on the declared mcp floor, 1747 pass and 6 skip on mcp 2.x, and 1722 pass / 31 skip with FCP_MCP_INDEX=off (CI runs all three; the extra skips there are the tests OF the cache). The other skips are the cases that need ffmpeg, PySceneDetect or Final Cut Pro present. Coverage spans models, parser, writer, FCPXMLWriter generation, server handlers, rough cut generation, speed cutting & pacing curves, marker pipeline, refactored helper functions, regression fixes, security hardening (XXE, entity expansion, path traversal, sandbox boundaries, minidom defense-in-depth, JSON depth limits, input validation, ffmpeg bounds, write-handler sandboxing), connected clips, roles, diff, export, compound clip flattening, audio track generation, templates, effects, .fcpxmld bundles with sidecar preservation, bulk media relink, real media silence detection, transcript-driven editing, filtergraph compilation, proxy rendering with artifact duration read-back, source-media visual checks, export watch detection, loopback bridge probing, EDL import, autopush, the operation journal and hash-checked undo, the deliver review gate, bulk organize edits, tiered shot search with its never-transcribes / never-downloads guards, the diversity constraint, the grouped tools dispatching to the flat handlers, the preview:// HTML render and its traversal/extension/null-byte/symlink rejection paths, the final-cut-pro skill, and DTD validation against Apple's official DTDs.

Several of those are mutation checks — they exist to prove an instrument can see the failure it is meant to catch, because a check that reads identically on a good and a bad result certifies nothing:

  • test_the_instrument_can_see_a_wrong_duration renders a one-second timeline and asserts the probe reads something other than two seconds.

  • test_the_waveform_is_actually_drawn renders the same video against loud and near-silent audio, so the filmstrips are identical by construction and any byte difference must come from the waveform. This one caught a real shipped defect: showwavespic draws on a transparent background that flattens to white, so a white trace was invisible while every ordinary check still passed.

  • test_the_edit_still_reports_success_when_the_push_fails proves an autopush failure never costs you a file that is already on disk.

  • test_a_touched_source_drops_its_rows re-exports a source and asserts the cache forgets it; with the (mtime, size) check removed the stale rows survive and the test goes red.

  • test_key_goes_in_the_header_and_nowhere_else — moving the ElevenLabs key into the URL makes it fail.

  • test_version.py asserts server.__version__ matches pyproject.toml; the two had disagreed since v0.17.0 without anything noticing.


Requirements

  • Python 3.10+ · Final Cut Pro 10.4+ (FCPXML 1.8+) · Claude Desktop or any MCP client

  • Dependencies (auto-installed): mcp (1.3.0+, including 2.x), defusedxml

  • ffmpeg (optional) — needed for silence analysis (detect_media_silence, remove_media_silence)

  • [scenes] extra (optional) — adds PySceneDetect for scenes detection that can see a cut between similar colours; without it the group falls back to ffmpeg's coarser scene filter and says so.

  • [find] extra (optional, Apple Silicon) — adds mlx-vlm + numpy so find can caption shots offline; without it find answers from transcript and metadata and says vision is unavailable.

  • [intelligence] extra (optional) — adds librosa for detect_beats; everything else works without it. Install via uvx --from "fcp-mcp-server[intelligence]" fcp-mcp-server or pip install "fcp-mcp-server[intelligence]" (from source: pip install -e '.[intelligence]').

  • See Compatibility for full version matrix


Ecosystem — XML Mode Today, Live Mode Next

This server is the safe, offline layer of FCP automation: no patched binaries, no private APIs, runs on managed Macs, works without Final Cut Pro installed. It composes with the live-control side of the ecosystem rather than competing with it:

  • SpliceKit by @elliotttate with @latenitefilms — live in-process control of a patched FCP copy with its own ~200-tool MCP server. The deep edit engine here and the live hands there are complementary by design; an optional bridge to SpliceKit's local JSON-RPC endpoint is on this project's roadmap (see below).

  • CommandPost by @latenitefilms — nine years of accessibility-layer FCP automation with a built-in WebSocket control surface; another candidate live backend.

The full ecosystem analysis and the dual-mode architecture plan live in docs/CAPABILITY-AUDIT-2026-06.md.


Roadmap

  • Core FCPXML parsing (reads v1.8–1.14, writes v1.13) — v0.8.0

  • .fcpxmld bundle support with object-tracking/Cinematic sidecar preservation — v0.8.0

  • Bulk media relink (relink_media) — v0.8.0

  • DTD validation against Apple's official DTDs — v0.8.0

  • Timeline analysis, markers, EDL/CSV export

  • Clip editing (trim, reorder, split, speed, transitions)

  • QC tools (flash frames, gaps, duplicates, health scoring)

  • Generation (rough cuts, montages, A/B roll, beat sync)

  • MCP Prompts + Resources (auto-discovery)

  • Subtitle & transcript import as markers

  • Multi-track (connected clips, compound clips, roles)

  • Timeline diff + social media reformat

  • Silence detection & cleanup

  • Cross-NLE export (DaVinci Resolve, Premiere Pro, Avid)

  • Live mode v1 — zero-click push-to-FCP via Apple events, AppleScript library inspection — v0.9.0

  • Watch-folder round-trip + backend Protocol refactor (operation layer shared by XML and Live)

  • Media intelligence v1 — real silence detection from source audio (detect_media_silence) — v0.10.0

  • Silence auto-removalremove_media_silence cuts real silence with ripple — v0.11.0

  • Beat detectiondetect_beats (librosa) chains into beat markers + snap-to-beats — v0.12.0

  • Transcript-based editing — local Whisper transcription, edit_by_transcript (remove/keep_only), filler-word removal — v0.13.0

  • 7 grouped toolsinspect/diagnose/edit/mark/generate/transcript/deliver replace the 62 flat tools as the advertised default, cutting the schema footprint 84.7%; FCP_MCP_LEGACY_TOOLS=1 keeps the 62 available — v0.14.0

  • preview:// HTML timeline render — see a cut without opening Final Cut Pro — v0.14.0

  • final-cut-pro Claude Code skill — workflow order + FCPXML gotchas — v0.14.0

  • Daily scheduled CI — catches upstream dependency breaks within 24h — v0.14.0

  • The Looppreview (see the edit from the source media), watch (notice the Cmd-E export), import_edl_json, bridge detection, autopush — v0.17.0

  • Speed and sight — SQLite analysis index with per-clip progress, scenes shot-boundary detection, transcript_pack, opt-in ElevenLabs Scribe diarization — v0.18.0

  • The moat and the ledger — operation journal + history/undo, review gate on deliver, organize bulk edits + organize_auto, find tiered shot search with offline MLX captions, diversity constraint — v0.19.0

  • Shot embeddings — tier-3 ranking is lexical over captions until embeddings land

  • Live bridges — optional SpliceKit / CommandPost adapters for in-app control when installed

  • Audio sync detection

  • Premiere Pro native XML support


Known Issues

Issue

Impact

Workaround

Still images crash FCP

PNG/JPEG assets referenced directly in FCPXML crash Final Cut Pro on import (addAssetClip null pointer). Confirmed across multiple format configurations, dimension matching, and element types.

Convert stills to short MOVs before referencing: ffmpeg -loop 1 -i image.png -c:v libx264 -t 2 -pix_fmt yuv420p -r 24 output.mov. This is an FCP limitation, not an FCPXML spec issue.

Non-standard timebases

FCP rejects time values with denominators outside its standard set (e.g. 100800/57600s). Cross-denominator arithmetic previously produced these.

Fixed in v0.5.29 — TimeValue arithmetic now uses LCM, and speed changes snap to frame boundaries in 2400-tick timebase.

Malformed frameDuration crash

A frameDuration with zero or negative denominator (e.g. "0/0s") in the writer's _detect_fps would silently produce 0.0 fps, causing downstream ZeroDivisionError in speed/trim operations. The parser already validated this correctly.

Fixed in v0.6.23 — writer now validates both numerator and denominator, falling back to 30.0 fps.

"Connection closed" on a PyPI install of 0.19.2–0.21.0

tools/ was missing from the published package, so the server raised ModuleNotFoundError at import, before it could answer initialize. The MCP client reports only "Connection closed". A git checkout never showed it.

Fixed in v0.21.1 — upgrade (uvx picks it up on the next run; pip install -U fcp-mcp-server otherwise). The publish workflow now installs the built wheel into a clean venv and runs initialize + tools/list before anything ships.

Duplicate clip names corrupt edits

When multiple spine clips share the same name (e.g. Interview_A ×4), operations using the name-indexed dict silently target the wrong clip (last-indexed instead of first). Affected: delete_clip, add_marker_at_timeline, trim_clip, change_speed, split_clip, add_transition, reorder_clips.

Fixed in v0.6.37–0.6.39 — all methods now resolve clips via _resolve_clip() which walks the spine directly, returning the first match.


Reporting a Problem

You do not need a GitHub account, and you do not need to be a programmer.

  • GitHub: open an issue — best for anything with a traceback or a sample FCPXML.

  • Email: dev@jamesdare.com — read directly, answered directly. If Claude did the diagnosis for you, paste its findings as-is; that is exactly how the v0.21.1 packaging bug was reported and it was correct in every particular.

If the client only says "Connection closed", the server died before it could answer. Run it by hand to see the real error:

uvx fcp-mcp-server          # or: python server.py from a checkout

A Python traceback here (import error, missing dependency) is the whole story; send that.

Want to try builds before they ship? Say so in the email — pre-release wheels go out to a small list of working editors.

Status & Contributing

Actively maintained — live-verified against FCP 12.2, with external contributions already merged and credited: @mikegrant25 (sandbox security fix, #6), @jardelapp (audio duration probing, #7), and Marty Hou, documentary editor, who reported the v0.19.2–0.21.0 packaging failure by email with a diagnosis that held on every point.

PRs welcome. If you're a video editor who codes (or a coder who edits), let's build this together.

Credits

Built by @DareDev256 — former music video director, now building AI tools for creators.

License

MIT — see LICENSE.

mcp-name: io.github.DareDev256/fcpxml-mcp-server

Available Tools

13 tools
deliverA

Get the edit out: export to other NLEs, CSV, EDL and stems, reformat, relink media, or push straight into a running Final Cut Pro. Exports and push refuse a cut with no rendered preview of its current state (pass confirm_unreviewed=true to ship anyway). Actions: export_csv, export_edl, export_fcp7_xml, export_resolve_xml, export_role_stems, reformat_timeline, relink_media, push_to_fcp, list_fcp_libraries.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden. It usefully discloses that exports and push refuse to run on a cut without a rendered preview and explains the confirm_unreviewed=true escape hatch. However, it does not mention side effects, mutating behavior of reformat_timeline or relink_media, permissions, or output behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loaded with the core purpose, followed by a critical behavioral warning. The action list overlaps with the enum but still usefully summarizes the tool's breadth without excessive detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a multi-action dispatcher with a nested args object and no output schema. The description does not explain per-action required arguments, return values, or how args should be structured for each action. The confirm_unreviewed detail helps but is not enough to make the tool safely callable for all nine actions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining the confirm_unreviewed=true flag and connecting action names to concrete output formats and workflows, which helps disambiguate the generic args object.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with a specific verb phrase ('Get the edit out') and resource (a cut/edit), and clearly differentiates it from siblings like inspect, diagnose, preview, and watch by focusing on export, reformat, relink, and push operations. It also names concrete outputs and actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear context for when to use the tool—when you need to export or move an edit elsewhere. However, it does not explicitly state when not to use it or name alternatives for related tasks, instead leaving that mostly to sibling names and inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diagnoseA

Find problems in a timeline: gaps, flash frames, duplicates, dead air, and beat structure. Read-only. Run before editing. Actions: validate_timeline, detect_gaps, detect_duplicates, detect_flash_frames, detect_silence_candidates, detect_media_silence, detect_beats, find_short_cuts, find_long_clips, diff_timelines.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral burden; it explicitly flags the tool as read-only and limits its behavior to the listed detection/validation actions. It does not disclose output format or per-action side-effect nuances, but for a no-annotation tool the core non-mutating behavior is clearly stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose, then usage, then a compact action list, with no filler. The action list is long but all entries are load-bearing for action selection, and the whole text remains scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The definition is adequate for a read-only diagnostic tool: purpose, read-only behavior, and action vocabulary are present. However, the 10 actions are heterogeneous and have no per-action argument breakdown or output description, so an agent may need supplemental information to invoke some actions with confidence.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already covers both parameters fully, and the description's action list mirrors the enum. It adds no per-action argument semantics beyond the schema's example, so the description earns the baseline score of 3 rather than extra credit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Find problems in a timeline') and enumerates concrete problem types and actions, so the tool's diagnostic role is clear. It does not explicitly differentiate itself from sibling tools like inspect or find, but the action vocabulary makes the intended scope fairly unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Read-only. Run before editing.' gives a clear temporal usage rule and implies it is a pre-edit analysis step rather than a mutation. It does not name alternatives or state when not to use it, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

editA

Change clips on the timeline: insert, delete, trim, split, reorder, retime, remove silence, and attach audio, B-roll or transitions. Writes a new file. Actions: insert_clip, delete_clips, trim_clip, split_clip, reorder_clips, change_speed, rapid_trim, add_transition, add_audio, add_connected_clip, assign_role, fill_gaps, fix_flash_frames, remove_silence_candidates, remove_media_silence.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden. It does disclose a key trait: 'Writes a new file', which suggests a non-destructive output model. However, it does not describe failure behavior, prerequisites, permissions, or whether the original file is left untouched, so the disclosure is only partial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose, immediately states the key side effect, and then lists all supported actions. The action list is long but useful; no sentences are wasted, though the list partially duplicates the enum in the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a complex tool with 15 actions, a generic nested args object, no output schema, and no annotations. The description covers the operation set and the new-file side effect, but it leaves per-action argument requirements, output location, and return behavior unexplained, which is a significant gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so a baseline of 3 applies. The description adds an example of args ('filepath') and names the action enum, but it does not explain what arguments each specific action needs beyond the generic 'args' object.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource ('Change clips on the timeline') and enumerates concrete operations, so an agent understands exactly what this tool does. The action list also separates it from read-only or output-oriented siblings like inspect, preview, and deliver.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use it: whenever timeline clip edits are needed. It does not explicitly contrast it with sibling tools or state when not to use it, leaving the routing decision mostly to the action names and general intent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

findA

Natural-language shot search. find_shots (filepath, query, limit=10, visual=false, clip_name?) ranks moments by what was said (transcript), what was logged (names, keywords, notes, markers, audio events) and, when a local vision model is installed, what the frames look like — the first line of every result names which tiers answered and why one could not. find_index (captions=true, backend) warms scenes and captions and reports which clips have no transcript (it never transcribes or goes online). find_to_timeline (min_source_separation=1, output_path?) assembles the hits into a _found selects reel and reports its diversity score. Actions: find_index, find_shots, find_to_timeline.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral disclosure burden. It reveals ranking criteria, the optional local vision model dependency, the constraint that find_index never transcribes or goes online, and what result elements are reported. It falls short of clarifying side effects for find_to_timeline, which appears to create a reel, and does not mention auth or failure behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense and front-loaded with the core purpose, then systematically covers each action. The final 'Actions:' enumeration is slightly redundant after the prose has already introduced all three actions, but it is harmless and aids quick parsing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers all three actions, their parameters, key constraints, and output hints, which is especially important given there is no output schema. Some details remain implicit, such as exact query syntax, clip_name format, and valid backend values, but the agent has enough context to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the schema only defines a generic args object, the description names the action-specific arguments and their meanings, such as filepath, query, limit, visual, clip_name, captions, backend, min_source_separation, and output_path. This goes well beyond the schema's bare example and effectively compensates for the lack of per-action schema detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear purpose, 'Natural-language shot search,' then enumerates three concrete actions with distinct resources and behaviors. Each action is described with a specific verb and expected outcome, making the tool's scope immediately understandable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong routing guidance by explaining what each of the three actions does and when it applies, including boundaries like 'it never transcribes or goes online.' It does not explicitly compare against sibling tools such as index or transcript, but the action-level guidance is sufficient for most invocation decisions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generateB

Build new timeline structure from source clips: rough cuts, montages, A/B roll, templates and compound clips. Actions: auto_rough_cut, generate_ab_roll, generate_montage, apply_template, create_compound_clip, flatten_compound_clip, import_edl_json.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure, but it only lists action names like flatten_compound_clip and import_edl_json. It does not explain side effects, whether operations mutate existing projects, required project state, or return behavior, leaving the tool mostly a black box.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded: one clear purpose sentence followed by a compact action list. There is no filler, and the structure makes the tool's scope immediately scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool exposes seven distinct operations with a nested args object, yet the description provides no per-action argument guidance, output expectations, or usage caveats. No annotations or output schema compensate, so the description is not complete enough for reliable invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the action enum and args object are already documented. The description repeats the action list but adds no additional meaning about what arguments each action needs or how args should be structured beyond the schema's single example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action and resource: 'Build new timeline structure from source clips', and enumerates seven concrete operations. It is clear what the tool does, though it does not explicitly differentiate itself from sibling tools like edit or organize.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The purpose statement and action list imply when to use the tool—when constructing new timeline structures—but no explicit conditions, exclusions, or alternatives are mentioned. The agent must infer the boundary against sibling tools rather than being told.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

indexA

The analysis cache under ~/.fcp-mcp/index.db. index_status shows what is cached and how old it is; index_build warms it for every source in a timeline (args: filepath, with_transcript); index_clear drops it. Every other tool works with the index off (FCP_MCP_INDEX=off) — this only makes the second question fast. Actions: index_status, index_build, index_clear.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it discloses the key behaviors: status reads cache metadata, build warms the cache, and clear is destructive ('drops it'). It also signals low risk by stating every other tool works with the index off. Return values and build-overwrite behavior are left implicit, but the core operation semantics are honestly described.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded with the resource and optionality, then lists the three actions. The final action list is slightly redundant with the earlier sentence, but overall every sentence contributes useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers all three actions and the cache's optional nature, but there is no output schema and it does not explain what each action returns. It also leaves 'the second question' vague and only states args for index_build, so an agent must infer the arg behavior for status and clear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers both parameters with 100% description coverage, so the baseline is 3. The description adds that index_build takes filepath and with_transcript, which helps because the schema's args object is generic, but it does not explain what with_transcript means or whether status/clear accept args. This is only a modest improvement over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies the resource (~/.fcp-mcp/index.db) and enumerates three concrete operations (index_status, index_build, index_clear), so an agent can tell this is the index-management tool. It is specific and not a tautology, though it does not explicitly contrast itself with a sibling alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The sentence 'Every other tool works with the index off... this only makes the second question fast' gives an explicit selection signal: the index is optional and purely for performance. It does not spell out when to prefer one sub-action over another in detailed scenarios, but the contextual guidance is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

inspectA

Read a timeline or project without changing it. Use this first to understand what you are working with. Actions: list_projects, analyze_timeline, analyze_pacing, list_clips, list_markers, list_roles, list_keywords, list_effects, list_templates, list_library_clips, list_compound_clips, list_connected_clips, filter_by_role.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure; the phrase 'without changing it' adequately communicates that this is a non-mutating, read-only operation. However, it does not describe return shapes, failure modes, or differences between the 13 actions, which leaves meaningful gaps for a dispatcher-style tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and usage guidance, then compactly lists the supported actions. The action list repeats the enum but is useful for quick comprehension in a dispatcher tool, and there is no wasteful prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

As a 13-action multiplexer with no annotations and no output schema, the description gives a solid high-level orientation but lacks per-action argument requirements and expected results. An agent would likely call obvious actions like list_projects correctly, but less obvious actions like filter_by_role are under-specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: both 'action' and 'args' have descriptions, and 'args' includes an example. The description itself adds no per-action parameter detail, so it remains at the baseline 3 without compensating for the generic args object.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a clear read-only verb and resource ('Read a timeline or project without changing it'), which immediately distinguishes it from mutating sibling tools like edit, mark, and generate. It further lists all 13 concrete actions it supports, leaving no confusion about what the tool is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'Use this first to understand what you are working with,' giving a strong contextual trigger for selecting this tool. It does not explicitly name excluded situations or direct the agent to alternative siblings for modifications, but the read-only phrasing vs. mutation-oriented siblings makes the boundary clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

markB

Add or import markers and chapters, including from SRT/VTT subtitles, transcripts, and beat analysis. Actions: add_marker, batch_add_markers, import_srt_markers, import_transcript_markers, import_beat_markers, snap_to_beats.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral disclosure burden. It does state that the tool adds/imports markers and chapters and lists the action names, which conveys basic mutating behavior. But it does not disclose side effects, whether existing markers are modified, prerequisites, or what happens after an import or snap operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loaded with the core purpose, followed by a compact action list. It is easy to skim, though the action list largely duplicates the schema's enum and adds little new information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a dispatch-style tool with six distinct actions and a nested args object, yet the description only names the actions and does not explain per-action arguments, expected inputs, or return behavior. An agent could not confidently call the correct action with correct arguments based solely on this definition.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is high at 100%, so the baseline is 3 even without parameter explanations in the description. The description adds source-type context for actions like SRT/VTT and transcript imports, but it does not explain what arguments each action requires beyond the generic filepath example in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb + resource ('Add or import markers and chapters') and enumerates the supported source types and action names. It is clearly a marker/chapter tool, so it is distinguishable from siblings like 'transcript' and 'edit', though it does not explicitly contrast itself with any sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage contexts via 'including from SRT/VTT subtitles, transcripts, and beat analysis', and the action list hints at the available operations. However, it gives no explicit guidance on when to choose this tool over an alternative, nor when one action should be used instead of another.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

organizeA

Bulk library logging and the ledger. organize_auto proposes keywords per clip from cached captions and the transcript (apply=true writes them). Select clips with clip_name (glob), keyword and/or role, then organize_keywords (keywords, mode add|remove|replace), organize_rate (rating favorite|rejected|clear) or organize_roles (audio_role, video_role); each writes a _organized copy. history lists every recorded operation for the file's folder (limit); undo (n) moves the outputs of the last n writes into the journal's undone/ folder — it never deletes and refuses when a file changed since it was written. Actions: organize_auto, organize_keywords, organize_rate, organize_roles, history, undo.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does so well. It discloses that apply=true writes keywords, that each operation writes a _organized copy, and that undo moves outputs to a journal folder, never deletes, and refuses when files changed since writing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and information-rich, but the single block of text contains several run-on clauses and the final 'Actions:' list partially duplicates what was already described inline and in the schema enum. It is not poorly sized, but structure and conciseness could be improved with bullets or clearer separation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex multi-action tool with no output schema and no annotations, the description covers the main actions, selection criteria, side effects, and undo safety. Minor gaps remain, such as exact return values for history and precise required arguments per action, but the description gives enough context for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only has action and args, but the description enriches both by explaining each action's relevant parameters such as clip_name, keyword, role, keywords, mode, rating, audio_role, video_role, and limit. It adds real meaning beyond the schema, though it does not provide a complete per-action argument spec.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as a bulk library logging and ledger utility, and enumerates specific operations like organize_auto, organize_keywords, organize_rate, organize_roles, history, and undo. This distinguishes it from the sibling tools by domain and action, though it does not name a sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a concrete workflow: select clips, then apply keywords, ratings, or roles; it also explains when history and undo are relevant. However, it does not explicitly compare this tool to alternatives or state when not to use it, so the usage guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

previewA

See the edit without opening Final Cut Pro. Render a proxy video of the timeline, a contact sheet of every cut, a single frame, or a filmstrip-plus-waveform check read from the SOURCE MEDIA rather than from the XML. Run preview_check to confirm a fix actually landed. Actions: preview_render, preview_sheet, preview_frame, preview_check, preview_timeline.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of explaining behavior. It usefully reveals that previews read from SOURCE MEDIA rather than from the XML and that Final Cut Pro need not be opened. However, it does not disclose whether rendered proxies or check outputs persist as files, what side effects occur, or what output format the agent should expect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact, front-loaded with the main value proposition, and every sentence adds information. It avoids restating the tool name or schema boilerplate and ends with a clean action list.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has five distinct actions, no output schema, and no annotations, yet the description never explains what each action returns or what arguments each action needs apart from a generic filepath example. An agent selecting between preview_render and preview_timeline would still lack enough detail to invoke the right action correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%: both action and args have descriptions, and action is an enum. The description reinforces the action meanings by naming the five action values and clarifying that the check reads source media, but it does not add detailed semantics for the args object beyond the schema's single example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear, concrete purpose: 'See the edit without opening Final Cut Pro.' It then enumerates exactly what the tool produces (proxy video, contact sheet, single frame, filmstrip-plus-waveform check) and lists all five actions. This is a specific verb-plus-resource statement that distinguishes preview from sibling tools like inspect or diagnose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a practical context for use: preview output can be generated from source media without launching Final Cut Pro, and preview_check should be run 'to confirm a fix actually landed.' It does not explicitly exclude cases or name alternative sibling tools, but it clearly indicates when preview is the right choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scenesA

Shot boundaries. detect_scenes reads every source in a timeline and reports cuts in timeline time (args: filepath, clip_name?, backend auto|content|adaptive|ffmpeg, threshold?, min_scene_len=0.5); scenes_to_markers writes a marker at each cut; scenes_split cuts the clips there. PySceneDetect via the scenes extra, ffmpeg without it — the result names which one answered. Actions: detect_scenes, scenes_to_markers, scenes_split.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does a good job: it discloses that detect_scenes reads every source, reports cuts in timeline time, writes markers, and performs splits. It also reveals the backend dependency on PySceneDetect vs ffmpeg and that the result names which backend answered, though it does not describe the exact return shape or whether splitting is destructive/reversible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loads 'Shot boundaries,' then packs the three actions plus backend behavior into a compact format. The inline argument list inside the first sentence makes parsing slightly harder, but every clause contributes useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a multi-action tool with no output schema and no annotations, the description leaves gaps: it does not describe the return value structure for detect_scenes, and it does not spell out the arguments required for scenes_to_markers and scenes_split. The action enum and filepath are covered, but an agent could still be unsure how to invoke two of the three actions correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only describes args as a generic object, so the description adds substantial meaning by enumerating filepath, clip_name, backend, threshold, and min_scene_len with optionality and a default. However, it does not specify which arguments apply to scenes_to_markers and scenes_split, so it is not fully complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool's domain with 'Shot boundaries' and names three distinct actions with specific outcomes: detect_scenes reports cuts, scenes_to_markers writes markers, and scenes_split cuts clips. This differentiates it from sibling tools like 'mark' and 'edit' by giving each action a specific verb and resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context by laying out the three operations and their sequential relationship: first detect, then optionally write markers or split. It does not explicitly name sibling alternatives or state when not to use this tool, so it falls just short of giving full exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

transcriptB

Transcribe source media locally and edit the timeline by what was SAID rather than by timecode. Also removes filler words. Actions: transcribe_media, edit_by_transcript, remove_filler_words, transcript_pack.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden; it does reveal local processing and the 'by what was SAID' approach. But it never states whether edit_by_transcript or remove_filler_words mutates the timeline/project, whether changes are reversible, or what transcript_pack returns. Important behavioral gaps remain for a tool that implies editing side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences plus an action list; the description front-loads the core value proposition and is easy to scan. The filler-word sentence slightly duplicates the remove_filler_words action name but still provides immediate comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a multi-action tool with no annotations and no output schema, and the description defines each action only by name, not by input/output or side-effect behavior. An agent would struggle to know which action to select in a given situation or what result to expect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers both parameters fully, including enum values and an args example, so the baseline is 3. The description repeats the action names but adds little meaning about expected args, return effects, or how each action customizes the args object.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a concrete capability—transcribe media locally and edit the timeline by spoken content rather than timecode—and lists the accepted actions, making the tool's purpose and scope clear. It distances itself from generic edit and generate siblings by emphasizing transcript-based editing and filler-word removal. However, it doesn't explicitly contrast itself with the sibling 'edit' tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Use cases are implied: editing by transcript or removing filler words. But there is no explicit when-to-use/when-not-to-use guidance, no named alternatives, and no exclusions. This is minimum viable but leaves routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

watchA

Close the round-trip. Watch the Final Cut Pro export folder, detect the XML the moment it lands, and diff it against the last one seen. Pair with deliver.push_to_fcp for a full loop: push in, edit, Cmd-E, watch_pull. Actions: watch_start, watch_status, watch_stop, watch_pull.

ParametersJSON Schema
NameRequiredDescriptionDefault
argsNoArguments for the chosen action, e.g. {"filepath": "/path/to/project.fcpxml"}.
actionYesWhich operation to run.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description must carry the behavioral burden. It does disclose stateful behavior: watching the folder, detecting the XML, and diffing against the last seen one. However, it does not explain the side effects or lifecycle semantics of the four actions, such as what watch_start begins, what watch_status reports, or what watch_pull returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it opens with the workflow value, then states the mechanism, then the companion tool, then the action list. The phrase 'Close the round-trip' is slightly jargon-heavy, but each sentence earns its place and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a multi-action dispatcher with no output schema and no annotations, so the description needs to explain each action's individual contract. It does not: watch_start, watch_status, and watch_stop are only named, not described, and there is no indication of return values, state persistence, or prerequisites beyond the general workflow pairing with deliver.push_to_fcp.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description lists the action enum values but adds no semantic detail beyond the schema's own 'Which operation to run' and the args example. It does not clarify which arguments each action requires.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Watch the Final Cut Pro export folder, detect the XML the moment it lands, and diff it against the last one seen.' This makes the tool's core function unmistakable and distinguishes it from siblings like deliver.push_to_fcp by framing it as the feedback step in a round-trip workflow.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit workflow guidance: 'Pair with deliver.push_to_fcp for a full loop: push in, edit, Cmd-E, watch_pull.' This tells the agent when in the process the tool belongs. It does not explicitly state when not to use it or name alternatives, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 75 tool updatesv0.22.1
    • Removedadd_audio
    • Removedadd_connected_clip
    • Removedadd_marker
    • Removedadd_transition
    • Removedanalyze_pacing
    • Removedanalyze_timeline
    • Removedapply_template
    • Removedassign_role
    • Removedauto_rough_cut
    • Removedbatch_add_markers
    • Removedchange_speed
    • Removedcreate_compound_clip
    • Removeddelete_clips
    • Addeddeliver
    • Removeddetect_beats
    • Removeddetect_duplicates
    • Removeddetect_flash_frames
    • Removeddetect_gaps
    • Removeddetect_media_silence
    • Removeddetect_silence_candidates
    • Addeddiagnose
    • Removeddiff_timelines
    • Addededit
    • Removededit_by_transcript
    • Removedexport_csv
    • Removedexport_edl
    • Removedexport_fcp7_xml
    • Removedexport_resolve_xml
    • Removedexport_role_stems
    • Removedfill_gaps
    • Removedfilter_by_role
    • Addedfind
    • Removedfind_long_clips
    • Removedfind_short_cuts
    • Removedfix_flash_frames
    • Removedflatten_compound_clip
    • Addedgenerate
    • Removedgenerate_ab_roll
    • Removedgenerate_montage
    • Removedimport_beat_markers
    • Removedimport_srt_markers
    • Removedimport_transcript_markers
    • Addedindex
    • Removedinsert_clip
    • Addedinspect
    • Removedlist_clips
    • Removedlist_compound_clips
    • Removedlist_connected_clips
    • Removedlist_effects
    • Removedlist_fcp_libraries
    • Removedlist_keywords
    • Removedlist_library_clips
    • Removedlist_markers
    • Removedlist_projects
    • Removedlist_roles
    • Removedlist_templates
    • Addedmark
    • Addedorganize
    • Addedpreview
    • Removedpush_to_fcp
    • Removedrapid_trim
    • Removedreformat_timeline
    • Removedrelink_media
    • Removedremove_filler_words
    • Removedremove_media_silence
    • Removedremove_silence_candidates
    • Removedreorder_clips
    • Addedscenes
    • Removedsnap_to_beats
    • Removedsplit_clip
    • Removedtranscribe_media
    • Addedtranscript
    • Removedtrim_clip
    • Removedvalidate_timeline
    • Addedwatch
  2. 7 tool updatesv0.13.1
    • Addedadd_marker
    • Addedassign_role
    • Addedbatch_add_markers
    • Addeddetect_gaps
    • Addedexport_edl
    • Addedlist_compound_clips
    • Addedlist_projects
  3. 10 tool updatesv0.13.0
    • Removedadd_marker
    • Removedassign_role
    • Removedbatch_add_markers
    • Removeddetect_gaps
    • Addededit_by_transcript
    • Removedexport_edl
    • Removedlist_compound_clips
    • Removedlist_projects
    • Addedremove_filler_words
    • Addedtranscribe_media
  4. 3 tool updatesv0.12.0
    • Addeddetect_beats
    • Addeddetect_media_silence
    • Addedremove_media_silence
  5. 3 tool updatesv0.9.0
    • Addedlist_fcp_libraries
    • Addedpush_to_fcp
    • Addedrelink_media
  6. 53 tool updatesv0.6.63
    • First observedadd_audio
    • First observedadd_connected_clip
    • First observedadd_marker
    • First observedadd_transition
    • First observedanalyze_pacing
    • First observedanalyze_timeline
    • First observedapply_template
    • First observedassign_role
    • First observedauto_rough_cut
    • First observedbatch_add_markers
    • First observedchange_speed
    • First observedcreate_compound_clip
    • First observeddelete_clips
    • First observeddetect_duplicates
    • First observeddetect_flash_frames
    • First observeddetect_gaps
    • First observeddetect_silence_candidates
    • First observeddiff_timelines
    • First observedexport_csv
    • First observedexport_edl
    • First observedexport_fcp7_xml
    • First observedexport_resolve_xml
    • First observedexport_role_stems
    • First observedfill_gaps
    • First observedfilter_by_role
    • First observedfind_long_clips
    • First observedfind_short_cuts
    • First observedfix_flash_frames
    • First observedflatten_compound_clip
    • First observedgenerate_ab_roll
    • First observedgenerate_montage
    • First observedimport_beat_markers
    • First observedimport_srt_markers
    • First observedimport_transcript_markers
    • First observedinsert_clip
    • First observedlist_clips
    • First observedlist_compound_clips
    • First observedlist_connected_clips
    • First observedlist_effects
    • First observedlist_keywords
    • First observedlist_library_clips
    • First observedlist_markers
    • First observedlist_projects
    • First observedlist_roles
    • First observedlist_templates
    • First observedrapid_trim
    • First observedreformat_timeline
    • First observedremove_silence_candidates
    • First observedreorder_clips
    • First observedsnap_to_beats
    • First observedsplit_clip
    • First observedtrim_clip
    • First observedvalidate_timeline

TDQS

A3.8/5.0
Disambiguation4/5

The thirteen tools map onto distinct workflow stages—inspect, diagnose, edit, deliver, preview, watch, etc.—so an agent can usually pick the right one by intent. Minor overlap exists between inspect and diagnose (both read-only analysis) and between scenes_split and edit.split_clip, but the descriptions separate general understanding from problem-finding and scene-boundary work.

Naming Consistency4/5

All tool names follow a consistent single-lowercase-word style, which is predictable after seeing a few. The main deviation is grammatical: most are verbs (inspect, edit, mark, watch, find) while transcript, index, and scenes are nouns, and the actual operations live inside as snake_case actions.

Tool Count5/5

With 13 tools, the server sits comfortably in the well-scoped range, and each tool represents a distinct phase of FCP XML editing: analysis, diagnostics, editing, marking, generation, transcription, delivery, preview, round-trip, indexing, scene detection, organization, and search. None feels redundant; the breadth is justified by the size of the domain.

Completeness5/5

The surface is unusually complete for the domain, covering inspection, diagnosis, editing, generation, metadata logging, transcription, export, preview, watch-loop integration, caching, scene detection, organization, and natural-language search. Read-only tools have write counterparts, output paths are verifiable, and there are no obvious dead-end workflows.

Maintenance

ActivityActive
ResponsivenessWithin a week

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DareDev256/fcp-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server