# FCP MCP Server - Implementation Roadmap Step-by-step plan to build all editing features. --- ## Current State ✅ **DONE:** - Repository structure - Basic parser (read FCPXML) - 10 read-only MCP tools - Claude Desktop integration config 🔄 **IN PROGRESS:** - Writer module architecture - Tool schemas for editing --- ## Implementation Order ### Sprint 1: Core Write Operations (Week 1) **Day 1-2: TimeValue & Writer Foundation** ``` Tasks: □ Implement TimeValue class with all operations □ Create FCPXMLWriter base class □ Implement _detect_fps() □ Implement _build_clip_index() □ Implement save() □ Write unit tests for TimeValue ``` **Day 3-4: Marker Operations** ``` Tasks: □ Implement add_marker() □ Implement batch_add_markers() □ Handle marker types (standard, chapter, todo) □ Handle marker colors □ Test with real FCP export □ Verify re-import into FCP ``` **Day 5-6: Trim Operations** ``` Tasks: □ Implement trim_clip() - absolute timecodes □ Implement trim_clip() - delta trimming □ Implement _ripple_after_clip() □ Test with ripple=True and ripple=False □ Edge case: trim to zero duration (should fail) □ Edge case: trim beyond clip bounds (should clamp) ``` **Day 7: Reorder Operations** ``` Tasks: □ Implement reorder_clips() - move to start/end □ Implement reorder_clips() - move to timecode □ Implement reorder_clips() - after/before clip □ Implement _recalculate_offsets() □ Test multi-clip moves ``` --- ### Sprint 2: Advanced Edit Operations (Week 2) **Day 1-2: Transitions** ``` Tasks: □ Implement add_transition() - cross-dissolve □ Implement add_transition() - fade variants □ Find FCP effect reference IDs □ Test position: start, end, both □ Handle transition overlap calculation ``` **Day 3-4: Speed Changes** ``` Tasks: □ Implement change_speed() - constant speed □ Implement change_speed() - speed ramps □ Create timeMap XML structure □ Test slow-mo (0.5x) and fast (2x) □ Test speed ramp with different curves □ Verify frame blending options ``` **Day 5-6: Split & Delete** ``` Tasks: □ Implement split_clip() - single split point □ Implement split_clip() - multiple split points □ Implement delete_clip() - with ripple □ Implement delete_clip() - with gap □ Test split preserves clip attributes □ Test delete updates clip index ``` **Day 7: Selection & Batch** ``` Tasks: □ Implement select_by_keyword() □ Implement batch_trim() □ Test keyword matching modes (any, all, none) □ Test batch operations on 10+ clips ``` --- ### Sprint 3: Auto Rough Cut (Week 3) **Day 1-2: Ingest Phase** ``` Tasks: □ Implement ingest_source_clips() □ Parse asset-clips from library exports □ Parse clips from event exports □ Extract all metadata (keywords, ratings, favorites) □ Test with 100+ clip library ``` **Day 3-4: Score Phase** ``` Tasks: □ Implement score_clips() □ Implement keyword matching scoring □ Implement rating/favorite scoring □ Implement duration fit scoring □ Test scoring produces sensible rankings ``` **Day 5-6: Select Phase** ``` Tasks: □ Implement select_clips_for_segment() □ Implement all priority modes □ Implement pacing-based duration calculation □ Test clip selection respects already_used □ Test segment duration targets ``` **Day 7: Assemble Phase** ``` Tasks: □ Implement assemble_rough_cut() □ Create proper FCPXML document structure □ Add asset resources correctly □ Add transitions between segments □ Test complete rough cut generation □ Import result into FCP - verify it works ``` --- ### Sprint 4: Polish & Ship (Week 4) **Day 1-2: Error Handling** ``` Tasks: □ Add validation for all inputs □ Graceful handling of malformed FCPXML □ Clear error messages for common issues □ Logging throughout ``` **Day 3-4: Integration Testing** ``` Tasks: □ Create test suite with real FCP exports □ Test each tool end-to-end □ Test tool combinations (marker + trim + reorder) □ Performance testing with large projects ``` **Day 5-6: Documentation** ``` Tasks: □ Complete README with all tools □ Add usage examples for each tool □ Create tutorial: "Your first rough cut" □ Add troubleshooting guide □ Record demo video ``` **Day 7: Launch** ``` Tasks: □ Final testing pass □ Version bump to 1.0.0 □ Push to GitHub □ Submit to MCP registry □ Write launch posts □ Share with FCP communities ``` --- ## Testing Strategy ### Unit Tests ```python # tests/test_timevalue.py def test_from_timecode_hmsf(): tv = TimeValue.from_timecode("00:01:30:15", fps=30) assert tv.to_seconds() == 90.5 def test_from_timecode_fcpxml(): tv = TimeValue.from_timecode("2700/30s") assert tv.to_seconds() == 90.0 def test_addition(): a = TimeValue(30, 30) # 1 second b = TimeValue(60, 30) # 2 seconds c = a + b assert c.to_seconds() == 3.0 def test_simplify(): tv = TimeValue(60, 30) simplified = tv.simplify() assert simplified.numerator == 2 assert simplified.denominator == 1 ``` ### Integration Tests ```python # tests/test_writer_integration.py def test_add_marker_reimports(): """Marker added by writer should be visible in FCP.""" # 1. Create modified FCPXML writer = FCPXMLWriter("fixtures/sample.fcpxml") writer.add_marker("clip_0", "00:00:10:00", "Test Marker", MarkerType.CHAPTER) writer.save("output/test_marker.fcpxml") # 2. Parse it back parser = FCPXMLParser("output/test_marker.fcpxml") timeline = parser.parse() # 3. Verify marker exists marker_names = [m.name for m in timeline.markers] assert "Test Marker" in marker_names def test_trim_preserves_structure(): """Trimming shouldn't corrupt other timeline elements.""" writer = FCPXMLWriter("fixtures/sample.fcpxml") original_clip_count = len(writer.clips) writer.trim_clip("clip_0", trim_end="-1s") writer.save("output/test_trim.fcpxml") parser = FCPXMLParser("output/test_trim.fcpxml") timeline = parser.parse() # Same number of clips assert len(timeline.clips) == original_clip_count ``` ### Golden Set Tests ```python # tests/golden_set.py """ Golden set: known-good FCPXML files that must parse correctly. If any fail, we broke backward compatibility. """ GOLDEN_FILES = [ "fixtures/golden/simple_timeline.fcpxml", "fixtures/golden/multicam_project.fcpxml", "fixtures/golden/compound_clips.fcpxml", "fixtures/golden/with_effects.fcpxml", "fixtures/golden/fcp_10_6_export.fcpxml", "fixtures/golden/fcp_10_7_export.fcpxml", "fixtures/golden/fcp_10_8_export.fcpxml", ] @pytest.mark.parametrize("filepath", GOLDEN_FILES) def test_golden_file_parses(filepath): parser = FCPXMLParser(filepath) timeline = parser.parse() assert timeline is not None assert len(timeline.clips) > 0 ``` --- ## Risk Mitigation ### Risk: FCPXML format changes between FCP versions **Mitigation:** - Test against multiple FCP export versions (10.6, 10.7, 10.8) - Use conservative parsing (ignore unknown elements) - Version detection in parser - Golden set tests for each version ### Risk: Generated FCPXML rejected by FCP **Mitigation:** - Always validate output XML - Round-trip testing (export → modify → import) - Use FCP's own exports as templates - Keep original attributes we don't understand ### Risk: Data loss from edit operations **Mitigation:** - Never overwrite original by default - Backup before destructive operations - Validate timeline integrity after each operation - Undo capability (save original state) ### Risk: Performance with large projects **Mitigation:** - Lazy loading of clip metadata - Index-based clip lookup - Stream parsing for very large files - Progress callbacks for long operations --- ## File Structure (Final) ``` fcp-mcp-server/ ├── server.py # MCP server entry point ├── fcpxml/ │ ├── __init__.py │ ├── parser.py # Read operations │ ├── writer.py # Write operations │ ├── rough_cut.py # Auto rough cut algorithm │ ├── models.py # Data classes │ └── utils.py # TimeValue, converters ├── tests/ │ ├── __init__.py │ ├── test_parser.py │ ├── test_writer.py │ ├── test_rough_cut.py │ ├── test_timevalue.py │ ├── golden_set.py │ └── fixtures/ │ ├── sample.fcpxml │ └── golden/ ├── examples/ │ ├── basic_usage.py │ ├── rough_cut_example.py │ └── batch_markers.py ├── docs/ │ ├── TOOL_REFERENCE.md │ ├── FCPXML_GUIDE.md │ └── TROUBLESHOOTING.md ├── pyproject.toml ├── requirements.txt ├── LICENSE └── README.md ``` --- ## Definition of Done A feature is complete when: 1. ✅ Code implemented and working 2. ✅ Unit tests passing 3. ✅ Integration test with real FCP export 4. ✅ Re-import into FCP verified 5. ✅ Error handling for edge cases 6. ✅ Documented in README 7. ✅ Example usage provided