Expand MCP to full AbletonOSC coverage: add 50+ tools, remove broken endpoints

New modules: return_track (11 tools), browser (6 tools), groove pool (3 tools).

Extended: clip (notes_extended, apply_note_modifications, automation envelopes,
warp markers, groove, quantize, velocity_amount, ram_mode), device (is_active,
chains, drum pads, chain parameters, randomize_macros), track (full I/O routing,
peak meters, duplicate_device, clips/is_playing, devices/can_have_chains),
scene (num_clips, clip_slots, fire_as_selected), view (show_clip/device_detail,
focus_browser, focused_document_view), song (jump_by, cue navigation,
return_track list, corrected scene_names address and cue_points parsing).

Removed 12 tools that called OSC addresses absent from this AbletonOSC build
(root_note, scale_name, ableton_link, cue_point/jump, set_or_delete_cue,
export/structure, midimap/map_cc, api log_level, view/set/selected_device).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 12:56:19 +02:00
parent 7260e9c43d
commit 5c274b9335
12 changed files with 706 additions and 260 deletions
+186 -158
View File
@@ -4,9 +4,9 @@ A full-featured [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
## Overview
**ableton-mcp** bridges AI assistants and Ableton Live by exposing **124 MCP tools** covering every major area of the Live API: transport control, track mixing, clip launching and editing, MIDI note manipulation, device parameter control, scene management, view selection, and real-time property listeners.
**ableton-mcp** bridges AI assistants and Ableton Live by exposing **160+ MCP tools** covering the full AbletonOSC API: transport, mixing, clips, MIDI notes, devices, scenes, return tracks, browser, groove pool, view navigation, and real-time listeners.
The server communicates with Ableton Live via [AbletonOSC](https://github.com/ideoforms/AbletonOSC) — a MIDI Remote Script that runs inside Live and exposes its internal API over OSC/UDP.
The server communicates with Ableton Live via AbletonOSC — a MIDI Remote Script that runs inside Live and exposes its internal API over OSC/UDP.
```
Claude (AI) ──MCP tools──▶ ableton-mcp ──OSC/UDP──▶ AbletonOSC ──Live Object Model──▶ Ableton Live
@@ -17,8 +17,8 @@ Claude (AI) ──MCP tools──▶ ableton-mcp ──OSC/UDP──▶ AbletonO
## Requirements
- **Ableton Live 11 or later**
- **Python 3.10+** (tested with 3.10.6 via pyenv)
- **AbletonOSC** installed as a MIDI Remote Script (see below)
- **Python 3.10+**
- **AbletonOSC** installed as a MIDI Remote Script
---
@@ -26,101 +26,77 @@ Claude (AI) ──MCP tools──▶ ableton-mcp ──OSC/UDP──▶ AbletonO
### 1. Install AbletonOSC in Ableton Live
1. Download or clone [AbletonOSC](https://github.com/ideoforms/AbletonOSC)
2. Copy the `AbletonOSC` folder into your Ableton User Library Remote Scripts directory:
1. Copy the `AbletonOSC` folder into your Ableton User Library Remote Scripts directory:
- **Windows:** `%USERPROFILE%\Documents\Ableton\User Library\Remote Scripts`
- **macOS:** `~/Music/Ableton/User Library/Remote Scripts`
3. Restart Ableton Live
4. Open **Preferences → Link, Tempo & MIDI → MIDI** and set one of the Control Surface slots to **AbletonOSC**
2. Restart Ableton Live
3. Open **Preferences → Link, Tempo & MIDI → MIDI** and set one of the Control Surface slots to **AbletonOSC**
AbletonOSC will now listen on **UDP port 11000** and reply on **port 11001**.
AbletonOSC listens on **UDP port 11000** and replies on **port 11001**.
### 2. Install ableton-mcp
```bash
# Clone the repo (rename the folder after cloning)
git clone https://github.com/your-user/ableton-mcp
cd ableton-mcp
# Create and activate a virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS/Linux
# Install
pip install -e .
```
### 3. Configure Claude Desktop
### 3. Configure Claude Code
Add the server to your Claude Desktop configuration file:
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
Add to `~/.claude/settings.json`:
```json
{
"mcpServers": {
"ableton": {
"command": "C:\\path\\to\\ableton-mcp\\.venv\\Scripts\\ableton-mcp.exe"
"ableton-mcp": {
"command": "C:\\path\\to\\ableton-mcp\\.venv\\Scripts\\ableton-mcp.exe",
"args": []
}
}
}
```
Restart Claude Desktop. The Ableton Live tools will appear automatically when a Live session is open.
Restart Claude Code. Tools appear automatically when a Live session is open.
---
## Configuration
All settings can be overridden via environment variables:
| Variable | Default | Description |
|---|---|---|
| `ABLETON_HOST` | `127.0.0.1` | AbletonOSC host address |
| `ABLETON_SEND_PORT` | `11000` | Port to send OSC commands to Live |
| `ABLETON_RECEIVE_PORT` | `11001` | Port to receive OSC replies from Live |
| `ABLETON_SEND_PORT` | `11000` | Port to send OSC to Live |
| `ABLETON_RECEIVE_PORT` | `11001` | Port to receive OSC from Live |
| `ABLETON_TIMEOUT` | `5.0` | Query timeout in seconds |
Example (Claude Desktop config with custom port):
```json
{
"mcpServers": {
"ableton": {
"command": "C:\\path\\to\\.venv\\Scripts\\ableton-mcp.exe",
"env": {
"ABLETON_TIMEOUT": "10.0"
}
}
}
}
```
---
## Tool Reference
### System (7 tools)
### System (5 tools)
| Tool | Description |
|---|---|
| `system_test_connection` | Ping AbletonOSC; returns `{connected, latency_ms}` |
| `system_get_version` | Get Ableton Live version `{major, minor}` |
| `system_get_cpu_usage` | Get average CPU process usage (0.01.0) |
| `system_get_cpu_usage` | Average CPU process usage (0.01.0) |
| `system_show_message` | Display a message in the Ableton status bar |
| `system_get_log_level` | Get current AbletonOSC log level |
| `system_set_log_level` | Set log level: `debug` / `info` / `warning` / `error` / `critical` |
| `system_reload_api` | Hot-reload all AbletonOSC modules |
---
### Song / Transport (48 tools)
### Song / Transport (38 tools)
#### Playback
| Tool | Description |
|---|---|
| `song_get_state` | Full snapshot: tempo, is_playing, loop, time sig, track/scene counts, groove, link, scale… |
| `song_get_state` | Full snapshot: tempo, is_playing, loop, time sig, track/scene/return counts, groove |
| `song_start_playing` | Start playback from current position |
| `song_stop_playing` | Stop playback |
| `song_continue_playing` | Resume without resetting to start |
@@ -132,6 +108,9 @@ Example (Claude Desktop config with custom port):
|---|---|
| `song_get_tempo` / `song_set_tempo` | Get/set BPM (20300) |
| `song_get_time` / `song_set_time` | Get/jump playhead position in beats |
| `song_jump_by` | Move playhead by ±N beats relative to current position |
| `song_jump_to_next_cue` | Jump to next cue point |
| `song_jump_to_prev_cue` | Jump to previous cue point |
| `song_get_time_signature` / `song_set_time_signature` | Get/set numerator + denominator |
#### Loop
@@ -163,38 +142,20 @@ Example (Claude Desktop config with custom port):
|---|---|
| `song_undo` / `song_redo` | Undo/redo |
#### Tracks
#### Tracks & Scenes
| Tool | Description |
|---|---|
| `song_get_tracks` | List all tracks with index and name |
| `song_create_audio_track` | Create audio track at index |
| `song_create_midi_track` | Create MIDI track at index |
| `song_create_return_track` | Create return/aux track |
| `song_delete_track` / `song_delete_return_track` | Delete track |
| `song_duplicate_track` | Duplicate a track |
#### Scenes
| Tool | Description |
|---|---|
| `song_get_return_tracks` | List all return tracks with index and name |
| `song_create_audio_track` / `song_create_midi_track` / `song_create_return_track` | Create tracks |
| `song_delete_track` / `song_delete_return_track` / `song_duplicate_track` | Delete/duplicate tracks |
| `song_get_scenes` | List all scenes with index and name |
| `song_create_scene` / `song_delete_scene` / `song_duplicate_scene` | Scene CRUD |
| `song_capture_and_insert_scene` | Capture session state as a new scene |
#### Cue Points
| Tool | Description |
|---|---|
| `song_get_cue_points` | List all cue points |
| `song_jump_to_cue` | Jump to cue by index or name |
| `song_add_or_delete_cue` | Toggle cue at current playhead |
| `song_set_cue_name` | Rename a cue point |
#### Scale & Link
| Tool | Description |
|---|---|
| `song_set_root_note` | Set root note (0=C … 11=B) |
| `song_set_scale_name` | Set scale name e.g. `"Major"`, `"Dorian"` |
| `song_set_ableton_link` | Enable/disable Ableton Link |
| `song_export_structure` | Export full session structure to JSON file |
| `song_get_cue_points` | List all cue points `{index, name, time}` |
---
@@ -202,52 +163,87 @@ Example (Claude Desktop config with custom port):
| Tool | Description |
|---|---|
| `track_get_info` | All track properties: name, volume, pan, mute, solo, arm, type, color, monitoring, meter slots, device count |
| `track_get_info` | All properties: name, volume, pan, mute, solo, arm, type, color, monitoring, slots, device count |
| `track_set_volume` | Volume (0.0=−∞, 0.85≈0 dB, 1.0=+6 dB) |
| `track_set_pan` | Panning (1.0=left, 0.0=center, +1.0=right) |
| `track_set_mute` | Mute / unmute |
| `track_set_solo` | Solo / unsolo |
| `track_set_arm` | Arm / disarm for recording |
| `track_set_mute` / `track_set_solo` / `track_set_arm` | Mute/solo/arm |
| `track_get_send` / `track_set_send` | Get/set send level to a return track |
| `track_set_name` | Rename a track |
| `track_set_color` | Set track color by palette index (069) |
| `track_stop_clips` | Stop all clips on a track |
| `track_set_monitoring` | Monitoring state: 0=Auto, 1=In, 2=Off |
| `track_set_monitoring` | Monitoring: 0=Auto, 1=In, 2=Off |
| `track_set_fold` | Fold/unfold a group track |
| `track_get_clips` | List session clips: index, name, length, color |
| `track_get_arrangement_clips` | List arrangement clips: index, name, length, start_time |
| `track_get_devices` | List devices: index, name, type, class_name |
| `track_get_meter` | Output meter levels: left, right, level |
| `track_delete_device` | Remove a device from the chain |
| `track_get_available_input_routing_types` | List available input routing options |
| `track_set_input_routing_type` / `track_set_output_routing_type` | Set I/O routing |
| `track_get_clips` | Session clips: index, name, length, color, is_playing |
| `track_get_arrangement_clips` | Arrangement clips: index, name, length, start_time |
| `track_get_devices` | Devices: index, name, type, class_name, can_have_chains |
| `track_get_meter` | Output meter: level, left, right, peak_left, peak_right |
| `track_delete_device` / `track_duplicate_device` | Remove/duplicate device |
| `track_get_input_routing` | Current input type + channel + available options |
| `track_set_input_routing_type` / `track_set_input_routing_channel` | Set input routing |
| `track_get_output_routing` | Current output type + channel + available options |
| `track_set_output_routing_type` / `track_set_output_routing_channel` | Set output routing |
---
### Clips (19 tools)
### Return Tracks (11 tools)
| Tool | Description |
|---|---|
| `clip_fire` | Launch a clip |
| `clip_stop` | Stop a playing clip |
| `clip_get_info` | All clip properties: name, length, playing state, loop, markers, pitch, gain, launch mode, warp, color |
| `clip_set_name` | Rename a clip |
| `clip_set_color` | Set clip color by palette index (069) |
| `clip_set_gain` | Set clip gain in dB |
| `clip_set_muted` | Mute/unmute a clip |
| `clip_set_looping` | Enable/disable loop |
| `clip_set_loop_points` | Set loop start + end in beats |
| `clip_set_markers` | Set start + end markers in beats |
| `clip_set_pitch` | Transpose: semitones (48 to +48) and cents (50 to +50) |
| `return_track_get_info` | All properties: name, mute, solo, color, volume, panning |
| `return_track_set_volume` / `return_track_set_panning` | Volume/pan |
| `return_track_set_mute` / `return_track_set_solo` | Mute/solo |
| `return_track_set_name` / `return_track_set_color` | Rename/recolor |
| `return_track_get_send` / `return_track_set_send` | Inter-return sends |
| `return_track_get_meter` | Output meter: level, left, right |
| `return_track_get_devices` | List devices on the return track |
---
### Clips (31 tools)
#### Playback & Properties
| Tool | Description |
|---|---|
| `clip_fire` / `clip_stop` | Launch/stop a clip |
| `clip_get_info` | All properties: name, length, playing state, loop, markers, pitch, gain, launch mode |
| `clip_set_name` / `clip_set_color` | Rename/recolor |
| `clip_set_gain` | Clip gain in dB |
| `clip_set_muted` | Mute/unmute |
| `clip_set_looping` / `clip_set_loop_points` | Enable loop and set start/end |
| `clip_set_markers` | Set clip start/end markers |
| `clip_set_pitch` | Transpose: semitones (48…+48) and cents (50…+50) |
| `clip_set_warp_mode` | Warp mode: 0=Beats, 1=Tones, 2=Texture, 3=Re-Pitch, 4=Complex, 5=Complex Pro |
| `clip_set_warping` | Enable/disable warping |
| `clip_set_launch_mode` | Launch mode: 0=Trigger, 1=Gate, 2=Toggle, 3=Repeat |
| `clip_set_launch_quantization` | Per-clip launch quantization (014) |
| `clip_set_legato` | Enable/disable legato mode |
| `clip_duplicate_loop` | Double loop length by duplicating content |
| `clip_get_notes` | Get MIDI notes (filterable by pitch range + time range) |
| `clip_add_notes` | Add MIDI notes: `[{pitch, start, duration, velocity, mute}, …]` |
| `clip_remove_notes` | Remove MIDI notes by pitch/time range |
| `clip_set_launch_mode` | 0=Trigger, 1=Gate, 2=Toggle, 3=Repeat |
| `clip_set_launch_quantization` | Per-clip quantization (014) |
| `clip_set_legato` | Enable/disable legato |
| `clip_set_velocity_amount` | Scale note velocities (0.01.0) |
| `clip_set_ram_mode` | Enable/disable RAM mode for audio clips |
| `clip_duplicate_loop` | Double loop by duplicating content |
| `clip_quantize` | Quantize MIDI notes (quantization enum + strength 0.01.0) |
#### MIDI Notes
| Tool | Description |
|---|---|
| `clip_get_notes` | Notes filtered by pitch/time range: `{pitch, start, duration, velocity, mute}` |
| `clip_get_notes_extended` | Extended notes with note_id, release_velocity, probability |
| `clip_add_notes` | Add notes: `[{pitch, start, duration, velocity, mute}, …]` |
| `clip_apply_note_modifications` | Modify existing notes by note_id |
| `clip_remove_notes` | Remove notes in pitch/time range |
#### Automation Envelopes
| Tool | Description |
|---|---|
| `clip_get_automation_envelope` | Get breakpoints `{time, value}` for a device param |
| `clip_create_automation_envelope` | Create envelope for a device param |
| `clip_clear_envelope` | Clear one param's envelope |
| `clip_clear_all_envelopes` | Clear all envelopes in a clip |
#### Warp & Groove
| Tool | Description |
|---|---|
| `clip_get_warp_markers` | Warp markers: `{beat_time, sample_time}` |
| `clip_get_groove` / `clip_set_groove` | Get/assign groove by name |
---
@@ -255,52 +251,84 @@ Example (Claude Desktop config with custom port):
| Tool | Description |
|---|---|
| `clip_slot_get_info` | Slot state: has_clip, is_playing, is_triggered, will_record, is_group_slot |
| `clip_slot_fire` | Trigger a slot (launches clip or starts recording if empty) |
| `clip_slot_stop` | Stop a slot |
| `clip_slot_create_clip` | Create a new empty MIDI clip with a given length in beats |
| `clip_slot_get_info` | State: has_clip, is_playing, is_triggered, will_record, is_group_slot |
| `clip_slot_fire` / `clip_slot_stop` | Trigger/stop a slot |
| `clip_slot_create_clip` | Create empty MIDI clip with given length in beats |
| `clip_slot_delete_clip` | Delete the clip in a slot |
| `clip_slot_duplicate_to` | Copy clip from one slot to another |
| `clip_slot_set_stop_button` | Enable/disable the stop button for a slot |
| `clip_slot_duplicate_to` | Copy clip to another slot |
| `clip_slot_set_stop_button` | Enable/disable slot stop button |
---
### Scenes (7 tools)
### Scenes (9 tools)
| Tool | Description |
|---|---|
| `scene_fire` | Launch a scene by index |
| `scene_fire_selected` | Launch the currently selected scene |
| `scene_get_info` | All scene properties: name, color, tempo, tempo_enabled, time sig, is_empty, is_triggered |
| `scene_set_name` | Rename a scene |
| `scene_set_color` | Set scene color by palette index (069) |
| `scene_set_tempo` | Override tempo for a scene (with enable toggle) |
| `scene_set_time_signature` | Override time signature for a scene |
| `scene_fire_as_selected` | Fire scene respecting follow actions |
| `scene_get_info` | All properties: name, color, tempo, time sig, is_empty, is_triggered |
| `scene_get_num_clips` | Number of clips in the scene |
| `scene_get_clip_slots` | Per-slot occupancy: `{slot_index, has_clip}` |
| `scene_set_name` / `scene_set_color` | Rename/recolor |
| `scene_set_tempo` | Override tempo (with enable toggle) |
| `scene_set_time_signature` | Override time signature |
---
### Devices (6 tools)
### Devices (15 tools)
| Tool | Description |
|---|---|
| `device_get_info` | Device info: name, type (audio_effect / instrument / midi_effect), class_name, num_parameters |
| `device_get_parameters` | All parameters: index, name, value, min, max, is_quantized |
| `device_get_parameter` | Single parameter: name, value, value_string (display value) |
| `device_set_parameter` | Set a parameter value (normalized 0.01.0) |
| `device_set_parameters_bulk` | Set multiple parameters in one call: `[{index, value}, …]` |
| `device_map_midi_cc` | Map a MIDI CC to a device parameter |
| `device_get_info` | Name, type, class_name, num_parameters, is_active |
| `device_get_is_active` / `device_set_is_active` | Get/set bypass state |
| `device_get_parameters` | All params: index, name, value, min, max, default_value, is_quantized |
| `device_get_parameter` | Single param: name, value, min, max, default_value, value_string |
| `device_set_parameter` | Set a parameter value (0.01.0 normalized) |
| `device_set_parameters_bulk` | Set multiple params: `[{index, value}, …]` |
| `device_randomize_macros` | Randomize rack macro knobs |
| `device_get_chains` | Rack chains: index, name, num_devices, device names |
| `device_get_drum_pads` | Drum Rack pads: index, name, note, mute, solo |
| `device_set_drum_pad_mute` / `device_set_drum_pad_solo` | Mute/solo a drum pad |
| `device_chain_get_parameter` | Get a param value inside a rack chain |
| `device_chain_set_parameter` | Set a param value inside a rack chain |
---
### View / Selection (5 tools)
### View / Navigation (8 tools)
| Tool | Description |
|---|---|
| `view_get_selection` | Current selection: selected_track, selected_scene, selected_clip, selected_device |
| `view_set_selected_track` | Select a track in the Ableton UI |
| `view_set_selected_scene` | Select a scene in the Ableton UI |
| `view_set_selected_clip` | Select a clip in the Ableton UI |
| `view_set_selected_device` | Select a device in the Ableton UI |
| `view_get_selection` | Selected track, scene, clip, and device |
| `view_get_focused_document_view` | Active view name (e.g. `'Session'`, `'Arranger'`) |
| `view_set_selected_track` | Select a track |
| `view_set_selected_scene` | Select a scene |
| `view_set_selected_clip` | Select a clip |
| `view_show_clip_detail` | Show clip detail panel |
| `view_show_device_detail` | Show device detail panel |
| `view_focus_browser` | Focus the browser panel |
---
### Browser (6 tools)
| Tool | Description |
|---|---|
| `browser_get_items` | List items in a category: `audio_effects` / `instruments` / `midi_effects` / `samples` / `sounds` / `clips` / `packs` / `plugins` |
| `browser_load_item` | Load an item into the selected track/slot (pass path parts as args) |
| `browser_preview_item` | Preview a sample or preset |
| `browser_stop_preview` | Stop browser preview playback |
| `browser_get_hotswap_target` | Name of device targeted for hotswap |
| `browser_begin_hotswap` | Begin hotswap mode for a device |
---
### Groove Pool (3 tools)
| Tool | Description |
|---|---|
| `groove_get_all` | List all groove names in the groove pool |
| `groove_get_amount` | Get groove intensity (0.01.0) by name |
| `groove_set_amount` | Set groove intensity (0.01.0) by name |
---
@@ -310,7 +338,7 @@ Subscribe to property changes from Ableton Live and poll them at any time.
| Tool | Description |
|---|---|
| `listener_start` | Register a listener for a property; returns the OSC response address |
| `listener_start` | Register a listener for a property |
| `listener_stop` | Unregister a listener |
| `listener_get_events` | Drain queued events (up to `max_events`); each event is a list of OSC args |
@@ -328,10 +356,6 @@ Subscribe to property changes from Ableton Live and poll them at any time.
| `clip` | any read/write property | requires `track_index` + `clip_index` |
| `clip_slot` | any property | requires `track_index` + `clip_index` |
**Example usage with Claude:**
> "Watch the beat and tell me the bar number every 4 bars"
> Claude calls `listener_start("song", "beat")`, then periodically `listener_get_events("song", "beat")`
---
## Example Prompts
@@ -342,14 +366,17 @@ Play the song from bar 3 at 128 BPM with the metronome on.
Create a 4-bar MIDI clip on track 0, slot 1, and add a C minor chord
(C3, Eb3, G3) on beats 1 and 3 with velocity 90.
Set every device on track 2 to a random-ish sound:
randomize all parameters whose name contains "Filter".
Load a reverb from the browser onto the first return track and set the
wet/dry to 50%.
Loop scene 4 forever: set scene 4's clips to looping and fire the scene.
Get all drum pad names on track 0's Drum Rack, then mute every pad
that isn't a kick or snare.
Solo track 3, mute tracks 1 and 2, and set track 3's reverb send to 0.4.
Solo track 3, set its reverb send to 0.4, and watch the output meter
until it clips.
Name all empty scenes "—" and delete any track with no clips.
Set the groove pool's first groove to 80% intensity and assign it to
all clips on track 1.
```
---
@@ -358,42 +385,43 @@ Name all empty scenes "—" and delete any track with no clips.
```
src/ableton_mcp/
├── server.py # FastMCP app; registers all tool modules
├── osc_client.py # Thread-safe OSCClient singleton
│ # cmd() fire-and-forget
│ # query() synchronous request/response
│ # start_listener() / drain_listener() real-time events
├── config.py # Port/host/timeout from env vars
├── server.py # FastMCP app; registers all tool modules
├── osc_client.py # Thread-safe OSCClient singleton
# cmd() fire-and-forget
# query() synchronous request/response
# start_listener() / drain_listener() real-time events
├── config.py # Port/host/timeout from env vars
└── tools/
├── song.py # Transport, tempo, loop, scenes, tracks, cues, scale, Link
├── track.py # Mixing, routing, devices list, meter
├── clip.py # Playback, MIDI notes, pitch, warp, loop, launch
├── clip_slot.py # Slot-level create/fire/delete/duplicate
├── scene.py # Scene fire, tempo/time-sig overrides
├── device.py # Parameter get/set (individual + bulk), MIDI CC mapping
├── view.py # Selected track/scene/clip/device
├── system.py # Connectivity, version, CPU, status bar, logging
── listener.py # Real-time property change subscriptions
├── song.py # Transport, tempo, loop, scenes, tracks, cues
├── track.py # Mixing, routing, devices list, meter
├── clip.py # Playback, MIDI notes, pitch, warp, loop, launch, envelopes
├── clip_slot.py # Slot-level create/fire/delete/duplicate
├── scene.py # Scene fire, info, clip slots, tempo/time-sig overrides
├── device.py # Parameters (individual + bulk), chains, drum pads
├── return_track.py# Return/aux track mixing and devices
├── browser.py # Content library browsing, load, preview, hotswap
── groove.py # Groove pool listing and amount control
├── view.py # Selected track/scene/clip, panel navigation
├── system.py # Connectivity, version, CPU, status bar
└── listener.py # Real-time property change subscriptions
```
**OSC communication** uses `python-osc` directly against AbletonOSC's full 200+ endpoint API. The `OSCClient` singleton runs a `ThreadingOSCUDPServer` on the receive port in a daemon thread. Queries use `threading.Event` for synchronous blocking with configurable timeout. Listeners store events in per-address `collections.deque` instances for thread-safe polling.
---
## Troubleshooting
**`system_test_connection` returns `connected: false`**
- Confirm AbletonOSC is enabled in Ableton → Preferences → Control Surfaces
- Make sure a Live project is open (AbletonOSC only activates with an open set)
- Check that no firewall is blocking UDP 11000/11001 on localhost
- Confirm AbletonOSC is enabled in Preferences → Control Surfaces
- A Live project must be open (AbletonOSC only activates with an open set)
- Check that no firewall blocks UDP 11000/11001 on localhost
**Timeout errors on queries**
**Timeout errors**
- Increase `ABLETON_TIMEOUT` env var (default 5 s)
- Some properties (e.g. `song_get_state`) issue many sequential OSC queries; slow machines may need a higher timeout
- `song_get_state` issues many sequential queries; slow machines may need 10 s+
**`No module named 'ableton_mcp'`**
- Make sure you installed with `pip install -e .` inside the correct `.venv`
- The Claude Desktop config `command` path must point to the `.venv` executable, not the system Python
- Install with `pip install -e .` inside the correct `.venv`
- The MCP config `command` path must point to the `.venv` executable
---