Skip to content

Arrangement View: full timeline workflow (switch view, playhead, clips, Session → Arrangement)#82

Open
Ooootto wants to merge 4 commits intoahujasid:mainfrom
Ooootto:main
Open

Arrangement View: full timeline workflow (switch view, playhead, clips, Session → Arrangement)#82
Ooootto wants to merge 4 commits intoahujasid:mainfrom
Ooootto:main

Conversation

@Ooootto
Copy link
Copy Markdown

@Ooootto Ooootto commented Mar 21, 2026

Summary

This PR adds Arrangement View support to AbletonMCP so assistants can help users build tracks from start to finish on the Arrangement timeline, not only in Session View.

Previously, the integration was strong for Session clips, instruments, and transport, but there was no way to switch to Arrangement, move the playhead in beats, inspect arrangement clips, or copy Session clips onto the Arrangement timeline. That made it hard to automate full song structure (intro → buildup → drop → outro) in the view most composers use for final arrangements.

What’s new

MCP tools (MCP_Server/server.py)

Tool Purpose
switch_to_arrangement_view Brings the main window to Arrangement View so the user (and assistant) can see the timeline being built.
set_arrangement_time Sets the song position / playhead in beats for precise section placement.
get_arrangement_clips Lists clips on the Arrangement timeline for a track (name, start/end, length, type).
duplicate_to_arrangement Copies a Session clip to the Arrangement at a given beat using Live’s duplicate_clip_to_arrangement (Ableton Live 11+).

Together, these enable a practical workflow: create or edit clips in Session, duplicate them to specific bar/beat positions on the Arrangement, jump the playhead to verify, and read back what’s on the timeline.

Remote script (AbletonMCP_Remote_Script/__init__.py)

  • Implements the corresponding commands and routes them through Live’s API (including arrangement clip iteration where available).
  • Documents the Session → Arrangement duplication path for agents in tool descriptions.

README

  • Highlights Arrangement View composition and an example prompt for full arrangements (intro, buildup, drop, breakdown, outro).

Performance

  • Refactor of AbletonConnection response handling: removes extra delays around state-changing commands so Arrangement (and other) operations feel snappier.

Why this matters

Most finished songs live on the Arrangement timeline. Exposing Arrangement-focused tools closes the loop: users can ask an MCP-connected assistant to help structure a full track in the same view they use for mixing and export, instead of being limited to clip launching and Session-only workflows.

Notes

  • duplicate_to_arrangement relies on APIs present in Live 11 / 12; older Live versions may not support all arrangement duplication features.

Thank you for maintaining AbletonMCP — happy to adjust naming, docs, or version guards based on your preferences.

Summary by CodeRabbit

  • New Features

    • Switch to Arrangement View directly
    • Set the current song time in arrangement
    • Retrieve arrangement clip metadata and timing information
    • Duplicate session clips to the arrangement
  • Documentation

    • Updated documentation reflecting expanded Arrangement View manipulation and composition capabilities

Ooootto and others added 4 commits March 15, 2026 21:42
Implemented new commands for switching to the Arrangement view, setting the current song time, retrieving arrangement clips, and duplicating session clips to the Arrangement timeline. Updated the server and remote script to support these features, enhancing the integration with Ableton Live's arrangement functionalities.ds
Removed unnecessary delays for state-modifying commands before and after receiving responses. This simplifies the response handling logic and improves the efficiency of command processing.
Add new arrangement view features to the README including arrangement composition, full song creation capabilities, and an example prompt for building complete arrangements with intro/buildup/drop/breakdown/outro sections.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Document arrangement view capabilities in README
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Add Arrangement View support for full song composition workflow

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add Arrangement View support with four new MCP tools for full song composition
  - switch_to_arrangement_view: Switch main window to Arrangement View
  - set_arrangement_time: Move playhead to specific beat position
  - get_arrangement_clips: List clips on arrangement timeline
  - duplicate_to_arrangement: Copy Session clips to arrangement at beat positions
• Refactor AbletonConnection response handling to remove unnecessary delays
• Update README with arrangement view capabilities and example prompts
Diagram
flowchart LR
  Session["Session View<br/>Clips & Instruments"]
  Duplicate["duplicate_to_arrangement<br/>Copy to Timeline"]
  Arrangement["Arrangement View<br/>Full Song Structure"]
  Playhead["set_arrangement_time<br/>Move Playhead"]
  Read["get_arrangement_clips<br/>Inspect Timeline"]
  
  Session -- "Copy clips" --> Duplicate
  Duplicate --> Arrangement
  Playhead --> Arrangement
  Arrangement --> Read
Loading

Grey Divider

File Changes

1. AbletonMCP_Remote_Script/__init__.py ✨ Enhancement +124/-4

Implement arrangement view command handlers

• Added three arrangement view command handlers: _switch_to_arrangement_view,
 _set_current_song_time, _duplicate_session_clip_to_arrangement
• Implemented _get_arrangement_clips to retrieve clips from arrangement timeline with metadata
• Registered arrangement commands in main thread task routing for state-modifying operations
• Added read-only arrangement command routing for get_arrangement_clips

AbletonMCP_Remote_Script/init.py


2. MCP_Server/server.py ✨ Enhancement +103/-14

Add arrangement tools and refactor response handling

• Added four new MCP tools: switch_to_arrangement_view, set_arrangement_time,
 get_arrangement_clips, duplicate_to_arrangement
• Registered arrangement commands as state-modifying in connection handler
• Removed pre and post-command delays (100ms each) for state-modifying commands
• Simplified response handling logic by eliminating unnecessary sleep calls

MCP_Server/server.py


3. README.md 📝 Documentation +5/-2

Document arrangement view capabilities

• Updated main description to highlight end-to-end track creation and arrangement manipulation
• Added "Arrangement view composition" as a key capability with section examples
• Updated Session control description to include Arrangement View
• Added arrangement composition example prompt to capabilities list

README.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Mar 21, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Remediation recommended

1. Arrangement query bypasses scheduler 🐞 Bug ⛯ Reliability
Description
The new get_arrangement_clips command calls _get_arrangement_clips directly from the client-handler
thread rather than using the existing schedule_message(main thread) execution path. This introduces
an inconsistent threading model for Live API access compared to other commands that are explicitly
routed to the main thread, increasing the chance of runtime failures depending on Live’s
thread-safety for arrangement clip iteration.
Code

AbletonMCP_Remote_Script/init.py[R344-347]

+            # Read-only arrangement command – no main-thread scheduling required
+            elif command_type == "get_arrangement_clips":
+                track_index = params.get("track_index", 0)
+                response["result"] = self._get_arrangement_clips(track_index)
Evidence
_handle_client runs in its own thread and calls _process_command; get_arrangement_clips currently
executes immediately in that thread, while many other commands use schedule_message to run on the
main thread.

AbletonMCP_Remote_Script/init.py[107-167]
AbletonMCP_Remote_Script/init.py[228-326]
AbletonMCP_Remote_Script/init.py[344-347]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`get_arrangement_clips` is executed directly in the client handler thread, bypassing the existing `schedule_message` main-thread execution pathway used for many Live-interacting commands.

### Issue Context
The remote script handles each TCP client in its own thread (`_handle_client`). Several commands are explicitly routed through `schedule_message(0, ...)` to run on Live’s main thread; `get_arrangement_clips` currently does not.

### Fix Focus Areas
- AbletonMCP_Remote_Script/__init__.py[228-350]

### Implementation notes
- Add `&quot;get_arrangement_clips&quot;` to the list of commands that are executed via `main_thread_task`.
- Add a `elif command_type == &quot;get_arrangement_clips&quot;: ...` branch inside `main_thread_task` that calls `_get_arrangement_clips(track_index)`.
- Remove (or avoid) the direct, non-scheduled `elif command_type == &quot;get_arrangement_clips&quot;` branch so the command always uses the scheduled pathway.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unguarded arrangement_clips access 🐞 Bug ✓ Correctness
Description
_get_arrangement_clips unconditionally iterates track.arrangement_clips even though the code
comments state it is only available in Live 11/12. On unsupported Live versions this will raise at
runtime and surface as an opaque tool failure rather than a clear “unsupported Live version/API”
error.
Code

AbletonMCP_Remote_Script/init.py[R693-704]

+            # track.arrangement_clips is available in Live 11 / 12
+            for clip in track.arrangement_clips:
+                clips.append({
+                    "name": clip.name,
+                    "start_time": clip.start_time,
+                    "end_time": clip.end_time,
+                    "length": clip.length,
+                    "color": clip.color,
+                    "is_midi_clip": clip.is_midi_clip,
+                    "is_audio_clip": clip.is_audio_clip,
+                    "is_playing": clip.is_playing
+                })
Evidence
The implementation uses track.arrangement_clips without checking attribute existence, despite
documenting the API as Live 11/12-only, and the server exposes this as a public MCP tool.

AbletonMCP_Remote_Script/init.py[679-705]
MCP_Server/server.py[678-694]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`_get_arrangement_clips` assumes `track.arrangement_clips` exists and will crash with an AttributeError on Live versions where it is unavailable.

### Issue Context
The code comment says `track.arrangement_clips` is available in Live 11/12, but there is no `hasattr`/capability check before using it.

### Fix Focus Areas
- AbletonMCP_Remote_Script/__init__.py[679-715]

### Implementation notes
- Before iterating, add a check like:
 - `if not hasattr(track, &#x27;arrangement_clips&#x27;):` then raise a `RuntimeError` (or return an error dict) with a clear message (e.g., &quot;Arrangement clips API requires Ableton Live 11+&quot;).
- Consider guarding per-clip attributes similarly if necessary (to keep the response stable across Live builds).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unguarded arrangement duplication call 🐞 Bug ✓ Correctness
Description
_duplicate_session_clip_to_arrangement calls track.duplicate_clip_to_arrangement without checking
the method exists, although the docstring states it’s only available in Live 11/12. On unsupported
Live versions this will raise at runtime and fail the duplicate_to_arrangement workflow with a
generic exception.
Code

AbletonMCP_Remote_Script/init.py[R719-746]

+        Uses the real Live API:
+          track.duplicate_clip_to_arrangement(clip, destination_time)
+
+        Available in Live 11 / 12.  destination_time is in beats from the
+        start of the arrangement.
+        """
+        try:
+            if track_index < 0 or track_index >= len(self._song.tracks):
+                raise IndexError("Track index out of range")
+
+            track = self._song.tracks[track_index]
+
+            if clip_index < 0 or clip_index >= len(track.clip_slots):
+                raise IndexError("Clip slot index out of range")
+
+            clip_slot = track.clip_slots[clip_index]
+
+            if not clip_slot.has_clip:
+                raise Exception(
+                    "No clip in slot " + str(clip_index) +
+                    " on track " + str(track_index)
+                )
+
+            clip = clip_slot.clip
+
+            # Duplicate to arrangement at the requested beat position
+            track.duplicate_clip_to_arrangement(clip, float(destination_time))
+
Evidence
The duplication implementation directly calls the Live 11/12-only API without feature detection, and
the server exposes this path as a tool intended for user workflows.

AbletonMCP_Remote_Script/init.py[716-746]
MCP_Server/server.py[697-740]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`_duplicate_session_clip_to_arrangement` assumes `track.duplicate_clip_to_arrangement` exists. On Live versions that don&#x27;t support it, the method call will raise and produce an unclear error.

### Issue Context
The docstring explicitly states the API is Live 11/12-only, but the implementation does not enforce/communicate this.

### Fix Focus Areas
- AbletonMCP_Remote_Script/__init__.py[716-756]

### Implementation notes
- Add a capability check before calling:
 - `if not hasattr(track, &#x27;duplicate_clip_to_arrangement&#x27;):` raise a `RuntimeError` with a clear message (e.g., &quot;Session→Arrangement duplication requires Ableton Live 11+&quot;).
- Keep the existing index/has_clip validation, but prefer raising a more specific exception type for &quot;no clip&quot; (optional).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 21, 2026

📝 Walkthrough

Walkthrough

The pull request extends the Ableton MCP remote script with arrangement view operations including switching to arrangement view, setting song time, retrieving arrangement clips, and duplicating session clips to the arrangement. The MCP server is updated with corresponding tool endpoints and command validation rules.

Changes

Cohort / File(s) Summary
Ableton MCP Remote Script
AbletonMCP_Remote_Script/__init__.py
Added four new arrangement-view handler methods (_switch_to_arrangement_view, _set_current_song_time, _get_arrangement_clips, _duplicate_session_clip_to_arrangement) with parameter validation and track/clip metadata extraction. Extended _process_command to route three main-thread commands via schedule_message and one reader command directly. Implemented dispatch cases in main_thread_task() for arrangement operations.
MCP Server Endpoints
MCP_Server/server.py
Added four new tool functions (switch_to_arrangement_view, set_arrangement_time, get_arrangement_clips, duplicate_to_arrangement) that send arrangement-related commands to the Ableton script. Extended command allowlist with new arrangement command types. Removed fixed 100ms pre/post delays for state-modifying commands.
Documentation
README.md
Updated feature descriptions to reflect arrangement view composition capabilities alongside session control, replacing generic wording with specific mention of "Arrangement view composition" and autonomous song section support (intro, buildup, drop, breakdown, outro).

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Server as MCP Server
    participant Script as Remote Script
    participant Ableton as Ableton Live

    Client->>Server: Call arrangement_time(time=120.0)
    Server->>Script: send_command("set_current_song_time", {time: 120.0})
    Script->>Script: _process_command() routes to main_thread_task()
    Script->>Script: main_thread_task() extracts time param
    Script->>Ableton: _set_current_song_time(120.0)
    Ableton->>Ableton: song.current_song_time = 120.0
    Ableton-->>Script: Updated time value
    Script-->>Server: {current_song_time: 120.0}
    Server-->>Client: "Song time set to 120.0 seconds"

    rect rgba(200, 150, 255, 0.5)
    Note over Client,Ableton: Alternative: Get Arrangement Clips
    end

    Client->>Server: Call get_arrangement_clips(track_index=0)
    Server->>Script: send_command("get_arrangement_clips", {track_index: 0})
    Script->>Script: _process_command() routes directly (non-main-thread)
    Script->>Ableton: _get_arrangement_clips(0)
    Ableton->>Ableton: Iterate track.arrangement_clips
    Ableton-->>Script: Clip metadata array
    Script-->>Server: {track_name, clips: [{name, start_time, end_time, ...}]}
    Server-->>Client: JSON with clip details
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Hops with glee, the arrangement's here!
Switch views quick, set timing clear,
Clips can dance from session space,
To arrangement's growing place. ✨🎵

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and comprehensively summarizes the main change: adding full Arrangement View timeline workflow support (view switching, playhead control, clip management, and Session-to-Arrangement duplication).
Docstring Coverage ✅ Passed Docstring coverage is 93.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes.

Add @coderabbitai placeholder anywhere in the title of your PR and CodeRabbit will replace it with a title based on the changes in the PR. You can change the placeholder by changing the reviews.auto_title_placeholder setting.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
MCP_Server/server.py (1)

661-675: Consider validating non-negative time values.

The time parameter accepts any float, but negative beat positions may not be meaningful in the arrangement timeline. While Live's API may handle this gracefully, adding a simple validation could provide better error messages.

🔧 Optional validation
 `@mcp.tool`()
 def set_arrangement_time(ctx: Context, time: float) -> str:
     """
     Move the arrangement playhead to a specific position.

     Parameters:
     - time: Position in beats from the start of the arrangement (e.g. 8.0 = bar 3 in 4/4)
     """
     try:
+        if time < 0:
+            return "Error: time must be non-negative"
         ableton = get_ableton_connection()
         result = ableton.send_command("set_current_song_time", {"time": time})
         return f"Playhead moved to beat {result.get('current_song_time', time)}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCP_Server/server.py` around lines 661 - 675, The set_arrangement_time
handler should validate that the time parameter is non-negative before calling
get_ableton_connection and ableton.send_command; add a check in
set_arrangement_time to return a clear error string (and log via logger.error)
when time < 0, and only call ableton.send_command("set_current_song_time",
{"time": time}) for valid non-negative values, preserving the existing
try/except for remote errors.
AbletonMCP_Remote_Script/__init__.py (2)

716-756: Same version guard recommendation applies here.

The track.duplicate_clip_to_arrangement method is also Live 11+ only. Adding a hasattr check would provide a clearer error message for Live 10 users.

🛡️ Suggested graceful degradation
             clip = clip_slot.clip

+            # duplicate_clip_to_arrangement requires Live 11+
+            if not hasattr(track, 'duplicate_clip_to_arrangement'):
+                raise RuntimeError(
+                    "duplicate_clip_to_arrangement is not available in this version of Live. "
+                    "This feature requires Live 11 or newer."
+                )
+
             # Duplicate to arrangement at the requested beat position
             track.duplicate_clip_to_arrangement(clip, float(destination_time))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AbletonMCP_Remote_Script/__init__.py` around lines 716 - 756, The
_duplicate_session_clip_to_arrangement function calls the Live 11+ API
track.duplicate_clip_to_arrangement without a version guard; add a
hasattr(track, "duplicate_clip_to_arrangement") check before calling it and
raise/log a clear, user-friendly error if the method is missing (e.g., indicate
Live 11+ required), so Live 10 users get a helpful message instead of a generic
exception; update the error path around track.duplicate_clip_to_arrangement to
perform this capability check and only call the method when present.

679-714: Consider adding a version guard or graceful degradation for Live 10.

The track.arrangement_clips property is only available in Live 11+. Since the README lists "Ableton Live 10 or newer" as a prerequisite, users on Live 10 will get an unclear AttributeError when calling this tool.

🛡️ Suggested graceful degradation
     def _get_arrangement_clips(self, track_index):
         """Return all clips placed in the Arrangement timeline for a track.
         ...
         """
         try:
             if track_index < 0 or track_index >= len(self._song.tracks):
                 raise IndexError("Track index out of range")

             track = self._song.tracks[track_index]
+
+            # track.arrangement_clips requires Live 11+
+            if not hasattr(track, 'arrangement_clips'):
+                raise RuntimeError(
+                    "arrangement_clips is not available in this version of Live. "
+                    "Arrangement View features require Live 11 or newer."
+                )
+
             clips = []

             # track.arrangement_clips is available in Live 11 / 12
             for clip in track.arrangement_clips:

Alternatively, consider updating the README to specify that Arrangement View features require Live 11+.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AbletonMCP_Remote_Script/__init__.py` around lines 679 - 714, The
_get_arrangement_clips method assumes track.arrangement_clips exists (Live 11+),
causing AttributeError on Live 10; add a version guard or fallback: detect
whether track has attribute arrangement_clips (e.g., hasattr(track,
"arrangement_clips")) before iterating, and if missing return a graceful
response (empty clips list or a clear message) or raise a descriptive exception;
update the method to reference self._song or API version if available, and
ensure the error path in _get_arrangement_clips logs a helpful message about
Live version compatibility instead of a raw AttributeError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@AbletonMCP_Remote_Script/__init__.py`:
- Around line 716-756: The _duplicate_session_clip_to_arrangement function calls
the Live 11+ API track.duplicate_clip_to_arrangement without a version guard;
add a hasattr(track, "duplicate_clip_to_arrangement") check before calling it
and raise/log a clear, user-friendly error if the method is missing (e.g.,
indicate Live 11+ required), so Live 10 users get a helpful message instead of a
generic exception; update the error path around
track.duplicate_clip_to_arrangement to perform this capability check and only
call the method when present.
- Around line 679-714: The _get_arrangement_clips method assumes
track.arrangement_clips exists (Live 11+), causing AttributeError on Live 10;
add a version guard or fallback: detect whether track has attribute
arrangement_clips (e.g., hasattr(track, "arrangement_clips")) before iterating,
and if missing return a graceful response (empty clips list or a clear message)
or raise a descriptive exception; update the method to reference self._song or
API version if available, and ensure the error path in _get_arrangement_clips
logs a helpful message about Live version compatibility instead of a raw
AttributeError.

In `@MCP_Server/server.py`:
- Around line 661-675: The set_arrangement_time handler should validate that the
time parameter is non-negative before calling get_ableton_connection and
ableton.send_command; add a check in set_arrangement_time to return a clear
error string (and log via logger.error) when time < 0, and only call
ableton.send_command("set_current_song_time", {"time": time}) for valid
non-negative values, preserving the existing try/except for remote errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21acfbd5-11b3-4bba-9ab3-48618a0c615f

📥 Commits

Reviewing files that changed from the base of the PR and between e008328 and ecd68bc.

📒 Files selected for processing (3)
  • AbletonMCP_Remote_Script/__init__.py
  • MCP_Server/server.py
  • README.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant