livepilot 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -5
- package/README.md +74 -17
- package/mcp_server/tools/devices.py +26 -10
- package/mcp_server/tools/mixing.py +10 -6
- package/mcp_server/tools/notes.py +1 -1
- package/mcp_server/tools/scenes.py +4 -6
- package/mcp_server/tools/tracks.py +2 -40
- package/package.json +2 -2
- package/plugin/plugin.json +2 -2
- package/plugin/skills/livepilot-core/SKILL.md +12 -12
- package/plugin/skills/livepilot-core/references/overview.md +7 -10
- package/remote_script/LivePilot/scenes.py +4 -4
- package/remote_script/LivePilot/tracks.py +1 -56
- package/remote_script/LivePilot/utils.py +7 -1
- package/LivePilot audit report.md +0 -87
package/CHANGELOG.md
CHANGED
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.0 — 2026-03-17
|
|
4
|
+
|
|
5
|
+
### Enhancements
|
|
6
|
+
- **Device tools now support return tracks and master track** — use negative `track_index` for return tracks (-1=A, -2=B) and -1000 for master track. Works with all 12 device tools: `get_device_info`, `get_device_parameters`, `set_device_parameter`, `batch_set_parameters`, `toggle_device`, `delete_device`, `load_device_by_uri`, `find_and_load_device`, `get_rack_chains`, `set_simpler_playback_mode`, `set_chain_volume`, `get_device_presets`
|
|
7
|
+
- **Mixing tools now support return tracks** — `set_track_volume`, `set_track_pan`, `get_track_routing`, `set_track_routing` accept negative indices for return tracks
|
|
8
|
+
- Fixed `quantize_clip` grid parameter documentation — was incorrectly documented as float beats, now correctly documented as integer enum (0-8)
|
|
9
|
+
- Fixed tempo range typo in SKILL.md (was 20-969, corrected to 20-999)
|
|
10
|
+
|
|
11
|
+
## 1.2.1 — 2026-03-17
|
|
12
|
+
|
|
13
|
+
### Fixes
|
|
14
|
+
- Remove 3 tools that don't work in Live 12's ControlSurface API: `create_group_track`, `freeze_track`, `flatten_track`
|
|
15
|
+
- Fix `set_scene_name` — now allows empty string to clear scene name
|
|
16
|
+
- Fix `set_scene_tempo` — removed invalid "0 to clear" (Live 12 range is 20-999 BPM)
|
|
17
|
+
- All 96 tools live-tested against Ableton Live 12
|
|
18
|
+
|
|
3
19
|
## 1.2.0 — 2026-03-17
|
|
4
20
|
|
|
5
|
-
### New Tools (+
|
|
6
|
-
- **`create_group_track`** — group a range of tracks into a foldable group track
|
|
21
|
+
### New Tools (+5, total 96)
|
|
7
22
|
- **`set_group_fold`** — fold/unfold a group track to show/hide children
|
|
8
|
-
- **`freeze_track`** — freeze a track to reduce CPU load
|
|
9
|
-
- **`flatten_track`** — flatten a frozen track to audio permanently
|
|
10
23
|
- **`set_track_input_monitoring`** — set input monitoring state (In/Auto/Off)
|
|
11
24
|
- **`set_clip_warp_mode`** — set warp mode for audio clips (Beats/Tones/Texture/Re-Pitch/Complex/Complex Pro)
|
|
12
25
|
- **`set_scene_color`** — set scene color (0-69)
|
|
13
|
-
- **`set_scene_tempo`** — set per-scene tempo that triggers on launch
|
|
26
|
+
- **`set_scene_tempo`** — set per-scene tempo that triggers on launch (20-999 BPM)
|
|
27
|
+
|
|
28
|
+
### Removed Tools (-3)
|
|
29
|
+
- **`create_group_track`** — removed due to Live 12 API limitations
|
|
30
|
+
- **`freeze_track`** — removed due to Live 12 API limitations
|
|
31
|
+
- **`flatten_track`** — removed due to Live 12 API limitations
|
|
14
32
|
|
|
15
33
|
### Enhancements
|
|
16
34
|
- `get_clip_info` now returns `is_midi_clip`, `is_audio_clip`, and audio warp fields (`warping`, `warp_mode`)
|
|
17
35
|
- `get_track_info` now returns `is_foldable`, `is_grouped`, `fold_state`, and `current_monitoring_state`
|
|
18
36
|
|
|
37
|
+
### Fixes
|
|
38
|
+
- `set_scene_name` now allows empty string to clear scene name
|
|
39
|
+
|
|
19
40
|
## 1.1.2 — 2026-03-17
|
|
20
41
|
|
|
21
42
|
### Fixes
|
package/README.md
CHANGED
|
@@ -11,18 +11,46 @@
|
|
|
11
11
|
[](https://github.com/dreamrec/LivePilot/actions/workflows/ci.yml)
|
|
12
12
|
[](https://github.com/dreamrec/LivePilot/stargazers)
|
|
13
13
|
|
|
14
|
-
**AI copilot for Ableton Live 12** —
|
|
14
|
+
**AI copilot for Ableton Live 12** — 96 MCP tools for music production, sound design, and mixing.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Talk to your DAW. Create tracks, program MIDI, load instruments, tweak parameters, arrange songs, and mix — all through natural language. LivePilot connects any MCP-compatible AI client (Claude, Cursor, VS Code Copilot) to Ableton Live and gives it full control over your session.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## What it feels like
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
You: "Set up a 126 BPM session with a drum track and a bass track"
|
|
24
|
+
Claude: Sets tempo to 126. Creates MIDI track "DRUMS" and "BASS".
|
|
25
|
+
Searches browser for a drum kit, loads "606 Core Kit".
|
|
26
|
+
Verifies kit loaded — Drum Rack with 16 chains. ✓
|
|
27
|
+
|
|
28
|
+
You: "Program a four-on-the-floor kick with offbeat hi-hats, 2 bars"
|
|
29
|
+
Claude: Creates 8-beat clip, adds kicks on every beat (pitch 36, velocity 110),
|
|
30
|
+
closed hats on offbeats (pitch 42, velocity 80/60 alternating).
|
|
31
|
+
Fires the clip.
|
|
32
|
+
|
|
33
|
+
You: "The hats are too loud, bring them down and add some swing"
|
|
34
|
+
Claude: Reads note IDs, modifies hat velocities to 65/45.
|
|
35
|
+
Adds ghost snare hits at 30% probability on the "e" and "ah".
|
|
36
|
+
The pattern evolves slightly every loop.
|
|
37
|
+
|
|
38
|
+
You: "Find an analog bass preset and write a simple sub line in D minor"
|
|
39
|
+
Claude: Searches instruments for "Analog Bass", loads a preset onto BASS track.
|
|
40
|
+
Adds root notes (D1 = pitch 38) with octave bounces.
|
|
41
|
+
Sets bass volume to 0.65, pans center. Fires to listen.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Every command goes through Ableton's official Live Object Model API. No hacks, no injection — the same interface Ableton's own control surfaces use. Everything is deterministic and reversible with undo.
|
|
17
45
|
|
|
18
46
|
---
|
|
19
47
|
|
|
20
48
|
## What You Can Do
|
|
21
49
|
|
|
22
50
|
- **Produce** — Create tracks, load instruments, program drum patterns, bass lines, chord progressions, and melodies
|
|
23
|
-
- **Arrange** — Build full song structures in arrangement view with MIDI
|
|
24
|
-
- **Design sounds** — Browse Ableton's library, load presets, tweak device
|
|
25
|
-
- **Mix** — Set levels, panning, sends, and routing. Run diagnostics to catch silent tracks and
|
|
51
|
+
- **Arrange** — Build full song structures in arrangement view with MIDI editing, cue points, automation, and timeline navigation
|
|
52
|
+
- **Design sounds** — Browse Ableton's library, load presets, tweak every device parameter, chain effects
|
|
53
|
+
- **Mix** — Set levels, panning, sends, and routing. Run diagnostics to catch silent tracks and stale solos
|
|
26
54
|
- **Iterate fast** — Transpose, humanize, quantize, duplicate, and reshape patterns through conversation
|
|
27
55
|
|
|
28
56
|
---
|
|
@@ -156,16 +184,16 @@ npx -y github:dreamrec/LivePilot --status
|
|
|
156
184
|
|
|
157
185
|
---
|
|
158
186
|
|
|
159
|
-
##
|
|
187
|
+
## 96 Tools Across 9 Domains
|
|
160
188
|
|
|
161
189
|
| Domain | Tools | What you can do |
|
|
162
190
|
|--------|:-----:|-----------------|
|
|
163
191
|
| **Transport** | 12 | Play/stop, tempo, time signature, loop, undo/redo, metronome, diagnostics |
|
|
164
|
-
| **Tracks** |
|
|
165
|
-
| **Clips** |
|
|
192
|
+
| **Tracks** | 14 | Create MIDI/audio/return tracks, name, color, mute, solo, arm, group fold, input monitoring |
|
|
193
|
+
| **Clips** | 11 | Create, delete, duplicate, fire, stop, loop settings, launch mode, warp mode |
|
|
166
194
|
| **Notes** | 8 | Add/get/remove/modify MIDI notes, transpose, quantize, duplicate |
|
|
167
195
|
| **Devices** | 12 | Load instruments & effects, tweak parameters, rack chains, presets |
|
|
168
|
-
| **Scenes** |
|
|
196
|
+
| **Scenes** | 8 | Create, delete, duplicate, fire, rename, color, per-scene tempo |
|
|
169
197
|
| **Mixing** | 8 | Volume, pan, sends, routing, return tracks, master |
|
|
170
198
|
| **Browser** | 4 | Search Ableton's library, browse categories, load presets |
|
|
171
199
|
| **Arrangement** | 19 | Create clips, full MIDI note CRUD, cue points, recording, automation |
|
|
@@ -176,11 +204,11 @@ npx -y github:dreamrec/LivePilot --status
|
|
|
176
204
|
### Transport (12)
|
|
177
205
|
`get_session_info` · `set_tempo` · `set_time_signature` · `start_playback` · `stop_playback` · `continue_playback` · `toggle_metronome` · `set_session_loop` · `undo` · `redo` · `get_recent_actions` · `get_session_diagnostics`
|
|
178
206
|
|
|
179
|
-
### Tracks (
|
|
180
|
-
`get_track_info` · `create_midi_track` · `create_audio_track` · `create_return_track` · `delete_track` · `duplicate_track` · `set_track_name` · `set_track_color` · `set_track_mute` · `set_track_solo` · `set_track_arm` · `stop_track_clips`
|
|
207
|
+
### Tracks (14)
|
|
208
|
+
`get_track_info` · `create_midi_track` · `create_audio_track` · `create_return_track` · `delete_track` · `duplicate_track` · `set_track_name` · `set_track_color` · `set_track_mute` · `set_track_solo` · `set_track_arm` · `stop_track_clips` · `set_group_fold` · `set_track_input_monitoring`
|
|
181
209
|
|
|
182
|
-
### Clips (
|
|
183
|
-
`get_clip_info` · `create_clip` · `delete_clip` · `duplicate_clip` · `fire_clip` · `stop_clip` · `set_clip_name` · `set_clip_color` · `set_clip_loop` · `set_clip_launch`
|
|
210
|
+
### Clips (11)
|
|
211
|
+
`get_clip_info` · `create_clip` · `delete_clip` · `duplicate_clip` · `fire_clip` · `stop_clip` · `set_clip_name` · `set_clip_color` · `set_clip_loop` · `set_clip_launch` · `set_clip_warp_mode`
|
|
184
212
|
|
|
185
213
|
### Notes (8)
|
|
186
214
|
`add_notes` · `get_notes` · `remove_notes` · `remove_notes_by_id` · `modify_notes` · `duplicate_notes` · `transpose_notes` · `quantize_clip`
|
|
@@ -188,8 +216,8 @@ npx -y github:dreamrec/LivePilot --status
|
|
|
188
216
|
### Devices (12)
|
|
189
217
|
`get_device_info` · `get_device_parameters` · `set_device_parameter` · `batch_set_parameters` · `toggle_device` · `delete_device` · `load_device_by_uri` · `find_and_load_device` · `get_rack_chains` · `set_simpler_playback_mode` · `set_chain_volume` · `get_device_presets`
|
|
190
218
|
|
|
191
|
-
### Scenes (
|
|
192
|
-
`get_scenes_info` · `create_scene` · `delete_scene` · `duplicate_scene` · `fire_scene` · `set_scene_name`
|
|
219
|
+
### Scenes (8)
|
|
220
|
+
`get_scenes_info` · `create_scene` · `delete_scene` · `duplicate_scene` · `fire_scene` · `set_scene_name` · `set_scene_color` · `set_scene_tempo`
|
|
193
221
|
|
|
194
222
|
### Mixing (8)
|
|
195
223
|
`set_track_volume` · `set_track_pan` · `set_track_send` · `get_return_tracks` · `get_master_track` · `set_master_volume` · `get_track_routing` · `set_track_routing`
|
|
@@ -215,7 +243,34 @@ The plugin adds production-focused skills, slash commands, and an autonomous pro
|
|
|
215
243
|
| `/mix` | Mixing assistant — levels, panning, sends |
|
|
216
244
|
| `/sounddesign` | Sound design workflow — instruments, effects, presets |
|
|
217
245
|
|
|
218
|
-
**Producer Agent** — An autonomous agent that builds tracks from high-level descriptions like *"Make me a 126 BPM rominimal track in D minor with hypnotic percussion"*.
|
|
246
|
+
**Producer Agent** — An autonomous agent that builds tracks from high-level descriptions like *"Make me a 126 BPM rominimal track in D minor with hypnotic percussion"*. It handles the full pipeline: track creation, instrument loading, pattern programming, effects, and mixing.
|
|
247
|
+
|
|
248
|
+
**Core Skill** — The `livepilot-core` skill teaches the AI how to work with Ableton properly: always read session state first, verify after every write, check that instruments actually loaded, never program notes at wrong pitches for drum kits. It's the difference between an AI that fumbles through the API and one that works like an experienced assistant.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## How It Compares
|
|
253
|
+
|
|
254
|
+
| Feature | LivePilot | [AbletonMCP](https://github.com/ahujasid/ableton-mcp) | [Ableton MCP Extended](https://github.com/uisato/ableton-mcp-extended) |
|
|
255
|
+
|---------|:---------:|:---------:|:---------:|
|
|
256
|
+
| **Tools** | 96 | ~20 | ~50 |
|
|
257
|
+
| **Arrangement view** | Full (clips, notes, cue points, automation) | No | Partial (automation "not perfect yet") |
|
|
258
|
+
| **MIDI note editing** | Full CRUD with note IDs, probability, velocity deviation | Basic add/get | Add/get/modify |
|
|
259
|
+
| **Device control** | Load, params, batch edit, rack chains, presets, Simpler modes | Load, basic params | Load, params |
|
|
260
|
+
| **Browser search** | Tree navigation, path filtering, URI-based loading | Basic search | Search with categories |
|
|
261
|
+
| **Mixing** | Volume, pan, sends, routing, master, diagnostics | Volume, pan | Volume, pan, sends |
|
|
262
|
+
| **Undo support** | Full (begin/end_undo_step wrapping) | No | Partial |
|
|
263
|
+
| **Session diagnostics** | Built-in health checks (armed tracks, solos, silent tracks) | No | No |
|
|
264
|
+
| **Per-note probability** | Yes (Live 12 API) | No | No |
|
|
265
|
+
| **Plugin/skills** | Claude Code plugin with 4 commands + producer agent | No | No |
|
|
266
|
+
| **Voice generation** | No | No | Yes (ElevenLabs) |
|
|
267
|
+
| **UDP low-latency mode** | No (TCP, reliable) | No | Yes (experimental) |
|
|
268
|
+
| **Protocol** | JSON/TCP, single-client, structured errors | JSON/TCP | JSON/TCP + UDP |
|
|
269
|
+
| **Installation** | Auto-detect CLI (`--install`) | Manual copy | Manual copy |
|
|
270
|
+
| **Live version** | Live 12 (modern note API) | Live 11+ | Live 11+ |
|
|
271
|
+
| **License** | MIT | MIT | MIT |
|
|
272
|
+
|
|
273
|
+
LivePilot focuses on **comprehensive, deterministic control** with safety nets (undo wrapping, diagnostics, verification patterns). It trades real-time parameter streaming (Extended's UDP mode) and external service integration (Extended's ElevenLabs) for deeper coverage of Ableton's core operations — especially arrangement, device management, and MIDI editing with Live 12's modern note API.
|
|
219
274
|
|
|
220
275
|
---
|
|
221
276
|
|
|
@@ -238,7 +293,9 @@ Claude / AI Client
|
|
|
238
293
|
└─────────────────────┘
|
|
239
294
|
```
|
|
240
295
|
|
|
241
|
-
Single-client TCP
|
|
296
|
+
All commands execute on Ableton's main thread via `schedule_message` — the same thread that handles the UI. This guarantees consistency with what you see on screen. Single-client TCP by design, because Ableton's Live Object Model is not thread-safe.
|
|
297
|
+
|
|
298
|
+
**Structured errors** with codes (`INDEX_ERROR`, `NOT_FOUND`, `INVALID_PARAM`, `STATE_ERROR`, `TIMEOUT`, `INTERNAL`) so the AI can understand what went wrong and recover.
|
|
242
299
|
|
|
243
300
|
---
|
|
244
301
|
|
|
@@ -23,9 +23,17 @@ def _get_ableton(ctx: Context):
|
|
|
23
23
|
return ctx.lifespan_context["ableton"]
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
MASTER_TRACK_INDEX = -1000
|
|
27
|
+
|
|
28
|
+
|
|
26
29
|
def _validate_track_index(track_index: int):
|
|
27
|
-
if track_index < 0:
|
|
28
|
-
|
|
30
|
+
if track_index < 0 and track_index != MASTER_TRACK_INDEX:
|
|
31
|
+
if track_index < -100:
|
|
32
|
+
raise ValueError(
|
|
33
|
+
"track_index must be >= 0 for regular tracks, "
|
|
34
|
+
"negative for return tracks (-1=A, -2=B), or -1000 for master"
|
|
35
|
+
)
|
|
36
|
+
# Negative values -1..-99 are valid return track indices
|
|
29
37
|
|
|
30
38
|
|
|
31
39
|
def _validate_device_index(device_index: int):
|
|
@@ -40,7 +48,8 @@ def _validate_chain_index(chain_index: int):
|
|
|
40
48
|
|
|
41
49
|
@mcp.tool()
|
|
42
50
|
def get_device_info(ctx: Context, track_index: int, device_index: int) -> dict:
|
|
43
|
-
"""Get info about a device: name, class, type, active state, parameter count.
|
|
51
|
+
"""Get info about a device: name, class, type, active state, parameter count.
|
|
52
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
44
53
|
_validate_track_index(track_index)
|
|
45
54
|
_validate_device_index(device_index)
|
|
46
55
|
return _get_ableton(ctx).send_command("get_device_info", {
|
|
@@ -51,7 +60,8 @@ def get_device_info(ctx: Context, track_index: int, device_index: int) -> dict:
|
|
|
51
60
|
|
|
52
61
|
@mcp.tool()
|
|
53
62
|
def get_device_parameters(ctx: Context, track_index: int, device_index: int) -> dict:
|
|
54
|
-
"""Get all parameters for a device with names, values, and ranges.
|
|
63
|
+
"""Get all parameters for a device with names, values, and ranges.
|
|
64
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
55
65
|
_validate_track_index(track_index)
|
|
56
66
|
_validate_device_index(device_index)
|
|
57
67
|
return _get_ableton(ctx).send_command("get_device_parameters", {
|
|
@@ -69,7 +79,8 @@ def set_device_parameter(
|
|
|
69
79
|
parameter_name: str | None = None,
|
|
70
80
|
parameter_index: int | None = None,
|
|
71
81
|
) -> dict:
|
|
72
|
-
"""Set a device parameter by name or index.
|
|
82
|
+
"""Set a device parameter by name or index.
|
|
83
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
73
84
|
_validate_track_index(track_index)
|
|
74
85
|
_validate_device_index(device_index)
|
|
75
86
|
if parameter_name is None and parameter_index is None:
|
|
@@ -95,7 +106,8 @@ def batch_set_parameters(
|
|
|
95
106
|
device_index: int,
|
|
96
107
|
parameters: Any,
|
|
97
108
|
) -> dict:
|
|
98
|
-
"""Set multiple device parameters in one call. parameters is a JSON array: [{name_or_index, value}].
|
|
109
|
+
"""Set multiple device parameters in one call. parameters is a JSON array: [{name_or_index, value}].
|
|
110
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
99
111
|
_validate_track_index(track_index)
|
|
100
112
|
_validate_device_index(device_index)
|
|
101
113
|
parameters = _ensure_list(parameters)
|
|
@@ -113,7 +125,8 @@ def batch_set_parameters(
|
|
|
113
125
|
|
|
114
126
|
@mcp.tool()
|
|
115
127
|
def toggle_device(ctx: Context, track_index: int, device_index: int, active: bool) -> dict:
|
|
116
|
-
"""Enable or disable a device.
|
|
128
|
+
"""Enable or disable a device.
|
|
129
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
117
130
|
_validate_track_index(track_index)
|
|
118
131
|
_validate_device_index(device_index)
|
|
119
132
|
return _get_ableton(ctx).send_command("toggle_device", {
|
|
@@ -125,7 +138,8 @@ def toggle_device(ctx: Context, track_index: int, device_index: int, active: boo
|
|
|
125
138
|
|
|
126
139
|
@mcp.tool()
|
|
127
140
|
def delete_device(ctx: Context, track_index: int, device_index: int) -> dict:
|
|
128
|
-
"""Delete a device from a track. Use undo to revert if needed.
|
|
141
|
+
"""Delete a device from a track. Use undo to revert if needed.
|
|
142
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
129
143
|
_validate_track_index(track_index)
|
|
130
144
|
_validate_device_index(device_index)
|
|
131
145
|
return _get_ableton(ctx).send_command("delete_device", {
|
|
@@ -136,7 +150,8 @@ def delete_device(ctx: Context, track_index: int, device_index: int) -> dict:
|
|
|
136
150
|
|
|
137
151
|
@mcp.tool()
|
|
138
152
|
def load_device_by_uri(ctx: Context, track_index: int, uri: str) -> dict:
|
|
139
|
-
"""Load a device onto a track using a browser URI string.
|
|
153
|
+
"""Load a device onto a track using a browser URI string.
|
|
154
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
140
155
|
_validate_track_index(track_index)
|
|
141
156
|
if not uri.strip():
|
|
142
157
|
raise ValueError("URI cannot be empty")
|
|
@@ -148,7 +163,8 @@ def load_device_by_uri(ctx: Context, track_index: int, uri: str) -> dict:
|
|
|
148
163
|
|
|
149
164
|
@mcp.tool()
|
|
150
165
|
def find_and_load_device(ctx: Context, track_index: int, device_name: str) -> dict:
|
|
151
|
-
"""Search the browser for a device by name and load it onto a track.
|
|
166
|
+
"""Search the browser for a device by name and load it onto a track.
|
|
167
|
+
track_index: 0+ for regular tracks, -1/-2/... for return tracks (A/B/...), -1000 for master."""
|
|
152
168
|
_validate_track_index(track_index)
|
|
153
169
|
if not device_name.strip():
|
|
154
170
|
raise ValueError("device_name cannot be empty")
|
|
@@ -14,13 +14,17 @@ def _get_ableton(ctx: Context):
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _validate_track_index(track_index: int):
|
|
17
|
-
if track_index <
|
|
18
|
-
raise ValueError(
|
|
17
|
+
if track_index < -100:
|
|
18
|
+
raise ValueError(
|
|
19
|
+
"track_index must be >= 0 for regular tracks, "
|
|
20
|
+
"or negative for return tracks (-1=A, -2=B)"
|
|
21
|
+
)
|
|
22
|
+
# Negative values -1..-99 are valid return track indices
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
@mcp.tool()
|
|
22
26
|
def set_track_volume(ctx: Context, track_index: int, volume: float) -> dict:
|
|
23
|
-
"""Set a track's volume (0.0-1.0)."""
|
|
27
|
+
"""Set a track's volume (0.0-1.0). Use negative track_index for return tracks (-1=A, -2=B)."""
|
|
24
28
|
_validate_track_index(track_index)
|
|
25
29
|
if not 0.0 <= volume <= 1.0:
|
|
26
30
|
raise ValueError("Volume must be between 0.0 and 1.0")
|
|
@@ -32,7 +36,7 @@ def set_track_volume(ctx: Context, track_index: int, volume: float) -> dict:
|
|
|
32
36
|
|
|
33
37
|
@mcp.tool()
|
|
34
38
|
def set_track_pan(ctx: Context, track_index: int, pan: float) -> dict:
|
|
35
|
-
"""Set a track's panning (-1.0 left to 1.0 right)."""
|
|
39
|
+
"""Set a track's panning (-1.0 left to 1.0 right). Use negative track_index for return tracks (-1=A, -2=B)."""
|
|
36
40
|
_validate_track_index(track_index)
|
|
37
41
|
if not -1.0 <= pan <= 1.0:
|
|
38
42
|
raise ValueError("Pan must be between -1.0 and 1.0")
|
|
@@ -81,7 +85,7 @@ def set_master_volume(ctx: Context, volume: float) -> dict:
|
|
|
81
85
|
|
|
82
86
|
@mcp.tool()
|
|
83
87
|
def get_track_routing(ctx: Context, track_index: int) -> dict:
|
|
84
|
-
"""Get input/output routing info for a track."""
|
|
88
|
+
"""Get input/output routing info for a track. Use negative track_index for return tracks (-1=A, -2=B)."""
|
|
85
89
|
_validate_track_index(track_index)
|
|
86
90
|
return _get_ableton(ctx).send_command("get_track_routing", {
|
|
87
91
|
"track_index": track_index,
|
|
@@ -97,7 +101,7 @@ def set_track_routing(
|
|
|
97
101
|
output_type: str | None = None,
|
|
98
102
|
output_channel: str | None = None,
|
|
99
103
|
) -> dict:
|
|
100
|
-
"""Set input/output routing for a track by display name."""
|
|
104
|
+
"""Set input/output routing for a track by display name. Use negative track_index for return tracks (-1=A, -2=B)."""
|
|
101
105
|
_validate_track_index(track_index)
|
|
102
106
|
params = {"track_index": track_index}
|
|
103
107
|
if input_type is not None:
|
|
@@ -53,10 +53,8 @@ def fire_scene(ctx: Context, scene_index: int) -> dict:
|
|
|
53
53
|
|
|
54
54
|
@mcp.tool()
|
|
55
55
|
def set_scene_name(ctx: Context, scene_index: int, name: str) -> dict:
|
|
56
|
-
"""Rename a scene."""
|
|
56
|
+
"""Rename a scene. Pass empty string to clear the name."""
|
|
57
57
|
_validate_scene_index(scene_index)
|
|
58
|
-
if not name.strip():
|
|
59
|
-
raise ValueError("Scene name cannot be empty")
|
|
60
58
|
return _get_ableton(ctx).send_command("set_scene_name", {
|
|
61
59
|
"scene_index": scene_index,
|
|
62
60
|
"name": name,
|
|
@@ -81,10 +79,10 @@ def set_scene_color(ctx: Context, scene_index: int, color_index: int) -> dict:
|
|
|
81
79
|
|
|
82
80
|
@mcp.tool()
|
|
83
81
|
def set_scene_tempo(ctx: Context, scene_index: int, tempo: float) -> dict:
|
|
84
|
-
"""Set scene tempo in BPM. Fires when the scene launches.
|
|
82
|
+
"""Set scene tempo in BPM (20-999). Fires when the scene launches."""
|
|
85
83
|
_validate_scene_index(scene_index)
|
|
86
|
-
if tempo
|
|
87
|
-
raise ValueError("Tempo must be
|
|
84
|
+
if tempo < 20 or tempo > 999:
|
|
85
|
+
raise ValueError("Tempo must be between 20.0 and 999.0 BPM")
|
|
88
86
|
return _get_ableton(ctx).send_command("set_scene_tempo", {
|
|
89
87
|
"scene_index": scene_index,
|
|
90
88
|
"tempo": tempo,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"""Track MCP tools — create, delete, rename, mute, solo, arm, group
|
|
1
|
+
"""Track MCP tools — create, delete, rename, mute, solo, arm, group fold, monitor.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
14 tools matching the Remote Script tracks domain.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from fastmcp import Context
|
|
@@ -148,30 +148,6 @@ def stop_track_clips(ctx: Context, track_index: int) -> dict:
|
|
|
148
148
|
return _get_ableton(ctx).send_command("stop_track_clips", {"track_index": track_index})
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
@mcp.tool()
|
|
152
|
-
def create_group_track(
|
|
153
|
-
ctx: Context,
|
|
154
|
-
start_index: int,
|
|
155
|
-
end_index: int,
|
|
156
|
-
name: str | None = None,
|
|
157
|
-
color: int | None = None,
|
|
158
|
-
) -> dict:
|
|
159
|
-
"""Create a group track containing tracks from start_index to end_index (inclusive)."""
|
|
160
|
-
_validate_track_index(start_index)
|
|
161
|
-
_validate_track_index(end_index)
|
|
162
|
-
if end_index < start_index:
|
|
163
|
-
raise ValueError("end_index must be >= start_index")
|
|
164
|
-
params = {"start_index": start_index, "end_index": end_index}
|
|
165
|
-
if name is not None:
|
|
166
|
-
if not name.strip():
|
|
167
|
-
raise ValueError("Track name cannot be empty")
|
|
168
|
-
params["name"] = name
|
|
169
|
-
if color is not None:
|
|
170
|
-
_validate_color_index(color)
|
|
171
|
-
params["color_index"] = color
|
|
172
|
-
return _get_ableton(ctx).send_command("create_group_track", params)
|
|
173
|
-
|
|
174
|
-
|
|
175
151
|
@mcp.tool()
|
|
176
152
|
def set_group_fold(ctx: Context, track_index: int, folded: bool) -> dict:
|
|
177
153
|
"""Fold or unfold a group track to show/hide its children."""
|
|
@@ -182,20 +158,6 @@ def set_group_fold(ctx: Context, track_index: int, folded: bool) -> dict:
|
|
|
182
158
|
})
|
|
183
159
|
|
|
184
160
|
|
|
185
|
-
@mcp.tool()
|
|
186
|
-
def freeze_track(ctx: Context, track_index: int) -> dict:
|
|
187
|
-
"""Freeze a track to reduce CPU load. Frozen tracks render to audio cache."""
|
|
188
|
-
_validate_track_index(track_index)
|
|
189
|
-
return _get_ableton(ctx).send_command("freeze_track", {"track_index": track_index})
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
@mcp.tool()
|
|
193
|
-
def flatten_track(ctx: Context, track_index: int) -> dict:
|
|
194
|
-
"""Flatten a frozen track to audio permanently. Use undo to revert."""
|
|
195
|
-
_validate_track_index(track_index)
|
|
196
|
-
return _get_ableton(ctx).send_command("flatten_track", {"track_index": track_index})
|
|
197
|
-
|
|
198
|
-
|
|
199
161
|
@mcp.tool()
|
|
200
162
|
def set_track_input_monitoring(ctx: Context, track_index: int, state: int) -> dict:
|
|
201
163
|
"""Set input monitoring (0=In, 1=Auto, 2=Off). Only for regular tracks, not return tracks."""
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"mcpName": "io.github.dreamrec/livepilot",
|
|
5
|
-
"description": "AI copilot for Ableton Live 12 —
|
|
5
|
+
"description": "AI copilot for Ableton Live 12 — 96 MCP tools for music production, sound design, and mixing",
|
|
6
6
|
"author": "Pilot Studio",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"type": "commonjs",
|
package/plugin/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "AI copilot for Ableton Live 12 —
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "AI copilot for Ableton Live 12 — 96 MCP tools for music production, sound design, and mixing",
|
|
5
5
|
"author": "Pilot Studio",
|
|
6
6
|
"skills": [
|
|
7
7
|
"skills/livepilot-core"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: livepilot-core
|
|
3
|
-
description: Core discipline for controlling Ableton Live 12 through LivePilot's
|
|
3
|
+
description: Core discipline for controlling Ableton Live 12 through LivePilot's 96 MCP tools. Use whenever working with Ableton Live through MCP tools.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# LivePilot Core — Ableton Live 12 AI Copilot
|
|
7
7
|
|
|
8
|
-
LivePilot gives you
|
|
8
|
+
LivePilot gives you 96 MCP tools to control Ableton Live 12 in real-time: transport, tracks, clips, MIDI notes, devices, scenes, mixing, browser, and arrangement.
|
|
9
9
|
|
|
10
10
|
## Golden Rules
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ LivePilot gives you 99 MCP tools to control Ableton Live 12 in real-time: transp
|
|
|
13
13
|
2. **Verify after every write** — re-read state to confirm your change took effect
|
|
14
14
|
3. **Use `undo` liberally** — it's your safety net. Mention it to users when doing destructive ops
|
|
15
15
|
4. **One operation at a time** — don't batch unrelated changes. Verify between steps
|
|
16
|
-
5. **Track indices are 0-based** — track 0 is the first track,
|
|
16
|
+
5. **Track indices are 0-based** — track 0 is the first track. Use negative indices for return tracks (-1=A, -2=B). Use -1000 for master track.
|
|
17
17
|
6. **Color indices 0-69** — Ableton's fixed palette. Don't guess — use the index
|
|
18
18
|
7. **Volume is 0.0-1.0, pan is -1.0 to 1.0** — these are normalized, not dB
|
|
19
19
|
8. **Tempo range 20-999 BPM** — validated before sending to Ableton
|
|
@@ -57,16 +57,16 @@ LivePilot gives you 99 MCP tools to control Ableton Live 12 in real-time: transp
|
|
|
57
57
|
- MIDI track with no instrument loaded
|
|
58
58
|
- Notes programmed but clip not fired
|
|
59
59
|
|
|
60
|
-
## Tool Domains (
|
|
60
|
+
## Tool Domains (96 total)
|
|
61
61
|
|
|
62
62
|
### Transport (12)
|
|
63
63
|
`get_session_info` · `set_tempo` · `set_time_signature` · `start_playback` · `stop_playback` · `continue_playback` · `toggle_metronome` · `set_session_loop` · `undo` · `redo` · `get_recent_actions` · `get_session_diagnostics`
|
|
64
64
|
|
|
65
|
-
### Tracks (
|
|
66
|
-
`get_track_info` · `create_midi_track` · `create_audio_track` · `create_return_track` · `delete_track` · `duplicate_track` · `set_track_name` · `set_track_color` · `set_track_mute` · `set_track_solo` · `set_track_arm` · `stop_track_clips`
|
|
65
|
+
### Tracks (14)
|
|
66
|
+
`get_track_info` · `create_midi_track` · `create_audio_track` · `create_return_track` · `delete_track` · `duplicate_track` · `set_track_name` · `set_track_color` · `set_track_mute` · `set_track_solo` · `set_track_arm` · `stop_track_clips` · `set_group_fold` · `set_track_input_monitoring`
|
|
67
67
|
|
|
68
|
-
### Clips (
|
|
69
|
-
`get_clip_info` · `create_clip` · `delete_clip` · `duplicate_clip` · `fire_clip` · `stop_clip` · `set_clip_name` · `set_clip_color` · `set_clip_loop` · `set_clip_launch`
|
|
68
|
+
### Clips (11)
|
|
69
|
+
`get_clip_info` · `create_clip` · `delete_clip` · `duplicate_clip` · `fire_clip` · `stop_clip` · `set_clip_name` · `set_clip_color` · `set_clip_loop` · `set_clip_launch` · `set_clip_warp_mode`
|
|
70
70
|
|
|
71
71
|
### Notes (8)
|
|
72
72
|
`add_notes` · `get_notes` · `remove_notes` · `remove_notes_by_id` · `modify_notes` · `duplicate_notes` · `transpose_notes` · `quantize_clip`
|
|
@@ -74,8 +74,8 @@ LivePilot gives you 99 MCP tools to control Ableton Live 12 in real-time: transp
|
|
|
74
74
|
### Devices (12)
|
|
75
75
|
`get_device_info` · `get_device_parameters` · `set_device_parameter` · `batch_set_parameters` · `toggle_device` · `delete_device` · `load_device_by_uri` · `find_and_load_device` · `set_simpler_playback_mode` · `get_rack_chains` · `set_chain_volume` · `get_device_presets`
|
|
76
76
|
|
|
77
|
-
### Scenes (
|
|
78
|
-
`get_scenes_info` · `create_scene` · `delete_scene` · `duplicate_scene` · `fire_scene` · `set_scene_name`
|
|
77
|
+
### Scenes (8)
|
|
78
|
+
`get_scenes_info` · `create_scene` · `delete_scene` · `duplicate_scene` · `fire_scene` · `set_scene_name` · `set_scene_color` · `set_scene_tempo`
|
|
79
79
|
|
|
80
80
|
### Mixing (8)
|
|
81
81
|
`set_track_volume` · `set_track_pan` · `set_track_send` · `get_return_tracks` · `get_master_track` · `set_master_volume` · `get_track_routing` · `set_track_routing`
|
|
@@ -144,7 +144,7 @@ When reading with `get_notes`, you also get:
|
|
|
144
144
|
Use `modify_notes` with `note_id` to update existing notes.
|
|
145
145
|
Use `remove_notes_by_id` for surgical deletion.
|
|
146
146
|
Use `transpose_notes` for pitch shifting a region.
|
|
147
|
-
Use `quantize_clip` to snap notes to a grid (grid=1
|
|
147
|
+
Use `quantize_clip` to snap notes to a grid (grid is an enum: 1=1/4, 2=1/8, 5=1/16, 8=1/32).
|
|
148
148
|
|
|
149
149
|
## Reference Corpus
|
|
150
150
|
|
|
@@ -152,7 +152,7 @@ Deep production knowledge lives in `references/`. Consult these when making crea
|
|
|
152
152
|
|
|
153
153
|
| File | What's inside | When to consult |
|
|
154
154
|
|------|--------------|-----------------|
|
|
155
|
-
| `references/overview.md` | All
|
|
155
|
+
| `references/overview.md` | All 96 tools mapped with params, units, ranges | Quick lookup for any tool |
|
|
156
156
|
| `references/midi-recipes.md` | Drum patterns by genre, chord voicings, scales, hi-hat techniques, humanization, polymetrics | Programming MIDI notes, building beats |
|
|
157
157
|
| `references/sound-design.md` | Stock instruments/effects, parameter recipes for bass/pad/lead/pluck, device chain patterns | Loading and configuring devices |
|
|
158
158
|
| `references/mixing-patterns.md` | Gain staging, parallel compression, sidechain, EQ by instrument, bus processing, stereo width | Setting volumes, panning, adding effects |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LivePilot Architecture & Tool Reference
|
|
2
2
|
|
|
3
|
-
LivePilot is an MCP server that controls Ableton Live 12 in real-time through
|
|
3
|
+
LivePilot is an MCP server that controls Ableton Live 12 in real-time through 96 tools across 9 domains. This document maps every tool to what it actually does in Ableton, so you know exactly which tool to reach for.
|
|
4
4
|
|
|
5
5
|
## Architecture
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
14
14
|
- **Protocol**: JSON over TCP, newline-delimited. Every command gets a response.
|
|
15
15
|
- **Thread safety**: All Live Object Model (LOM) access happens on Ableton's main thread
|
|
16
16
|
|
|
17
|
-
## The
|
|
17
|
+
## The 96 Tools — What Each One Does
|
|
18
18
|
|
|
19
19
|
### Transport (12) — Playback, tempo, global state, diagnostics
|
|
20
20
|
|
|
@@ -33,7 +33,7 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
33
33
|
| `get_recent_actions` | Returns log of recent commands sent to Ableton (newest first) | `limit` (1-50, default 20) |
|
|
34
34
|
| `get_session_diagnostics` | Analyzes session for issues: armed tracks, solo leftovers, unnamed tracks, empty clips | — |
|
|
35
35
|
|
|
36
|
-
### Tracks (
|
|
36
|
+
### Tracks (14) — Create, delete, configure, group tracks
|
|
37
37
|
|
|
38
38
|
| Tool | What it does | Key params |
|
|
39
39
|
|------|-------------|------------|
|
|
@@ -41,7 +41,6 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
41
41
|
| `create_midi_track` | Creates a new MIDI track | `index` (-1=end), `name`, `color` (0-69) |
|
|
42
42
|
| `create_audio_track` | Creates a new audio track | `index` (-1=end), `name`, `color` (0-69) |
|
|
43
43
|
| `create_return_track` | Creates a new return track | — |
|
|
44
|
-
| `create_group_track` | Groups a range of tracks into a group track | `start_index`, `end_index`, `name`, `color` |
|
|
45
44
|
| `delete_track` | Deletes a track | `track_index` |
|
|
46
45
|
| `duplicate_track` | Duplicates track with all contents | `track_index` |
|
|
47
46
|
| `set_track_name` | Renames a track | `track_index`, `name` |
|
|
@@ -51,8 +50,6 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
51
50
|
| `set_track_arm` | Arms/disarms for recording | `track_index`, `armed` (bool) |
|
|
52
51
|
| `stop_track_clips` | Stops all playing clips on track | `track_index` |
|
|
53
52
|
| `set_group_fold` | Folds/unfolds a group track | `track_index`, `folded` (bool) |
|
|
54
|
-
| `freeze_track` | Freezes a track to reduce CPU | `track_index` |
|
|
55
|
-
| `flatten_track` | Flattens a frozen track to audio (use undo to revert) | `track_index` |
|
|
56
53
|
| `set_track_input_monitoring` | Sets input monitoring state | `track_index`, `state` (0=In, 1=Auto, 2=Off) |
|
|
57
54
|
|
|
58
55
|
### Clips (11) — Clip lifecycle, properties, warp
|
|
@@ -82,7 +79,7 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
82
79
|
| `modify_notes` | Changes existing notes (pitch, time, velocity, probability) | `track_index`, `clip_index`, `modifications` |
|
|
83
80
|
| `duplicate_notes` | Copies notes in a region | `track_index`, `clip_index`, region params |
|
|
84
81
|
| `transpose_notes` | Shifts pitch of notes in a region | `track_index`, `clip_index`, `semitones`, region params |
|
|
85
|
-
| `quantize_clip` | Snaps notes to grid | `track_index`, `clip_index`, `grid` (
|
|
82
|
+
| `quantize_clip` | Snaps notes to grid | `track_index`, `clip_index`, `grid` (int 0-8: 0=None,1=1/4,2=1/8,5=1/16,8=1/32), `amount` (0-1) |
|
|
86
83
|
|
|
87
84
|
**Note format** (for `add_notes`):
|
|
88
85
|
```json
|
|
@@ -123,7 +120,7 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
123
120
|
| `fire_scene` | Launches all clips in a scene | `scene_index` |
|
|
124
121
|
| `set_scene_name` | Renames a scene | `scene_index`, `name` |
|
|
125
122
|
| `set_scene_color` | Sets scene color | `scene_index`, `color_index` (0-69) |
|
|
126
|
-
| `set_scene_tempo` | Sets tempo that triggers when scene fires
|
|
123
|
+
| `set_scene_tempo` | Sets tempo that triggers when scene fires | `scene_index`, `tempo` (20-999 BPM) |
|
|
127
124
|
|
|
128
125
|
### Mixing (8) — Levels, panning, routing
|
|
129
126
|
|
|
@@ -184,8 +181,8 @@ Claude Code ──MCP──► FastMCP Server ──TCP/9878──► Remote
|
|
|
184
181
|
| Velocity | 1-127 | 1 = softest, 127 = loudest |
|
|
185
182
|
| Probability | 0.0-1.0 | 1.0 = always triggers |
|
|
186
183
|
| Color index | 0-69 | Ableton's fixed palette |
|
|
187
|
-
| Track index | 0-based |
|
|
188
|
-
| Grid (quantize) |
|
|
184
|
+
| Track index | 0-based | Negative for return tracks (-1=A, -2=B), -1000 for master |
|
|
185
|
+
| Grid (quantize) | Integer enum (0-8) | 0=None, 1=1/4, 2=1/8, 3=1/8T, 4=1/8+T, 5=1/16, 6=1/16T, 7=1/16+T, 8=1/32 |
|
|
189
186
|
| Time signature | num/denom | denom must be power of 2 |
|
|
190
187
|
|
|
191
188
|
## Common Patterns
|
|
@@ -86,14 +86,14 @@ def set_scene_color(song, params):
|
|
|
86
86
|
|
|
87
87
|
@register("set_scene_tempo")
|
|
88
88
|
def set_scene_tempo(song, params):
|
|
89
|
-
"""Set a scene's tempo (BPM).
|
|
89
|
+
"""Set a scene's tempo (BPM, 20-999)."""
|
|
90
90
|
scene_index = int(params["scene_index"])
|
|
91
91
|
scene = get_scene(song, scene_index)
|
|
92
92
|
tempo = float(params["tempo"])
|
|
93
|
-
if tempo
|
|
94
|
-
raise ValueError("Tempo must be
|
|
93
|
+
if tempo < 20 or tempo > 999:
|
|
94
|
+
raise ValueError("Tempo must be between 20 and 999 BPM")
|
|
95
95
|
scene.tempo = tempo
|
|
96
96
|
return {
|
|
97
97
|
"index": scene_index,
|
|
98
|
-
"tempo": scene.tempo
|
|
98
|
+
"tempo": scene.tempo,
|
|
99
99
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
LivePilot - Track domain handlers (
|
|
2
|
+
LivePilot - Track domain handlers (14 commands).
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from .router import register
|
|
@@ -235,39 +235,6 @@ def stop_track_clips(song, params):
|
|
|
235
235
|
return {"index": track_index, "stopped": True}
|
|
236
236
|
|
|
237
237
|
|
|
238
|
-
@register("create_group_track")
|
|
239
|
-
def create_group_track(song, params):
|
|
240
|
-
"""Create a group track containing the specified track range."""
|
|
241
|
-
start = int(params["start_index"])
|
|
242
|
-
end = int(params["end_index"])
|
|
243
|
-
tracks = list(song.tracks)
|
|
244
|
-
if start < 0 or start >= len(tracks):
|
|
245
|
-
raise IndexError(
|
|
246
|
-
"start_index %d out of range (0..%d)" % (start, len(tracks) - 1)
|
|
247
|
-
)
|
|
248
|
-
if end < start or end >= len(tracks):
|
|
249
|
-
raise IndexError(
|
|
250
|
-
"end_index %d out of range (%d..%d)" % (end, start, len(tracks) - 1)
|
|
251
|
-
)
|
|
252
|
-
# Select the range of tracks, then use the API
|
|
253
|
-
song.view.selected_track = tracks[start]
|
|
254
|
-
for i in range(start, end + 1):
|
|
255
|
-
tracks[i].is_part_of_selection = True
|
|
256
|
-
song.create_group_track()
|
|
257
|
-
# The new group track is inserted at start_index
|
|
258
|
-
new_tracks = list(song.tracks)
|
|
259
|
-
group_track = new_tracks[start]
|
|
260
|
-
if "name" in params:
|
|
261
|
-
group_track.name = str(params["name"])
|
|
262
|
-
if "color_index" in params:
|
|
263
|
-
group_track.color_index = int(params["color_index"])
|
|
264
|
-
return {
|
|
265
|
-
"index": start,
|
|
266
|
-
"name": group_track.name,
|
|
267
|
-
"is_foldable": group_track.is_foldable,
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
|
|
271
238
|
@register("set_group_fold")
|
|
272
239
|
def set_group_fold(song, params):
|
|
273
240
|
"""Fold or unfold a group track."""
|
|
@@ -282,28 +249,6 @@ def set_group_fold(song, params):
|
|
|
282
249
|
}
|
|
283
250
|
|
|
284
251
|
|
|
285
|
-
@register("freeze_track")
|
|
286
|
-
def freeze_track(song, params):
|
|
287
|
-
"""Freeze a track to reduce CPU load."""
|
|
288
|
-
track_index = int(params["track_index"])
|
|
289
|
-
track = get_track(song, track_index)
|
|
290
|
-
if track_index < 0:
|
|
291
|
-
raise ValueError("Cannot freeze a return track")
|
|
292
|
-
track.freeze()
|
|
293
|
-
return {"index": track_index, "frozen": True}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
@register("flatten_track")
|
|
297
|
-
def flatten_track(song, params):
|
|
298
|
-
"""Flatten a frozen track to audio (irreversible — use undo to revert)."""
|
|
299
|
-
track_index = int(params["track_index"])
|
|
300
|
-
track = get_track(song, track_index)
|
|
301
|
-
if track_index < 0:
|
|
302
|
-
raise ValueError("Cannot flatten a return track")
|
|
303
|
-
track.flatten()
|
|
304
|
-
return {"index": track_index, "flattened": True}
|
|
305
|
-
|
|
306
|
-
|
|
307
252
|
@register("set_track_input_monitoring")
|
|
308
253
|
def set_track_input_monitoring(song, params):
|
|
309
254
|
"""Set input monitoring state for a track (0=In, 1=Auto, 2=Off)."""
|
|
@@ -39,9 +39,15 @@ def error_response(request_id, message, code=INTERNAL):
|
|
|
39
39
|
|
|
40
40
|
# ── Validation helpers ───────────────────────────────────────────────────────
|
|
41
41
|
|
|
42
|
+
MASTER_TRACK_INDEX = -1000
|
|
43
|
+
|
|
44
|
+
|
|
42
45
|
def get_track(song, track_index):
|
|
43
46
|
"""Return a track by index (0-based). Supports negative indices for
|
|
44
|
-
return tracks: -1 = first return, -2 = second return, etc.
|
|
47
|
+
return tracks: -1 = first return, -2 = second return, etc.
|
|
48
|
+
Use -1000 for the master track."""
|
|
49
|
+
if track_index == MASTER_TRACK_INDEX:
|
|
50
|
+
return song.master_track
|
|
45
51
|
tracks = list(song.tracks)
|
|
46
52
|
if track_index < 0:
|
|
47
53
|
return_tracks = list(song.return_tracks)
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Deep audit of the **LivePilot** repository and comparison with other AI‑enabled DAW assistants
|
|
2
|
-
|
|
3
|
-
## Overview of LivePilot
|
|
4
|
-
|
|
5
|
-
**LivePilot** is an open‑source Model Context Protocol (MCP) server and companion plug‑in that connects large language models to *Ableton Live 12*. The project’s goal is to act as an **AI co‑pilot** for music production, sound design and mixing.
|
|
6
|
-
|
|
7
|
-
* **Purpose and capabilities:** The README explains that LivePilot exposes **91 tools across nine domains** (transport, tracks, clips, notes, devices, scenes, mixing, browser and arrangement)【665853537458845†L43-L70】. It allows a user to create tracks, program MIDI patterns, load instruments, adjust mixing parameters and even build full song structures via natural‑language requests【665853537458845†L15-L21】. The tool set covers nearly every aspect of a typical Ableton workflow: starting/stopping playback, setting tempo, creating MIDI or audio tracks, renaming and coloring them, creating/duplicating clips, reading and editing MIDI notes, loading devices and presets, changing levels/pans/sends, browsing Ableton’s library, editing arrangement clips and automation【665853537458845†L43-L70】. Each tool maps directly to an Ableton Live API call; the manual notes that there is **no abstraction layer** – commands are deterministic and reversible【608977690485721†L23-L27】.
|
|
8
|
-
* **Architecture:** A natural‑language prompt is processed by the AI client (e.g., Claude Code or Cursor) and sent over the MCP to the **LivePilot server** (Python with `fastmcp`)【665853537458845†L90-L97】. The server validates inputs and forwards them via a single‑client TCP connection to a **Remote Script** that runs inside Ableton’s Python environment【665853537458845†L90-L97】. The Remote Script executes commands on Ableton’s main thread (the same thread as the GUI), ensuring thread‑safe access to the Live Object Model【608977690485721†L29-L34】. Installation is streamlined via `npx -y github:dreamrec/LivePilot --install`, which copies the Remote Script to Ableton’s user library and sets up the MCP server【665853537458845†L22-L29】.
|
|
9
|
-
* **Plugin and producer agent:** LivePilot includes a Claude Code plug‑in that provides slash commands (`/session`, `/beat`, `/mix`, `/sounddesign`) and an **autonomous producer agent** that can build complete tracks from high‑level descriptions (“Make me a 126 BPM rominimal track…”)【665853537458845†L82-L89】. The core skill packaged with the plug‑in teaches the AI how to use LivePilot effectively – checking session state before issuing commands, verifying the results after writes and avoiding common mistakes【692402510651097†L69-L81】.
|
|
10
|
-
* **Documentation and user guidance:** The manual is comprehensive. It explains installation, connectivity, examples of natural‑language sessions, the details of each tool, production workflows, MIDI programming guidelines, sound design recipes, mixing tips and troubleshooting【608977690485721†L40-L47】. The getting‑started guide shows how to connect the server, then suggests an example conversation (“What’s in my session?” → “Set the tempo to 120 and create a MIDI track called DRUMS” → “Search for a drum kit and load it onto the DRUMS track” → “Create an 8‑beat clip and program a basic house kick pattern…”)【692402510651097†L39-L51】.
|
|
11
|
-
* **Compatibility:** LivePilot supports Ableton Live 12 (any edition) and requires Python 3.10 or newer and Node.js 18+【665853537458845†L96-L102】. Arrangement‑related tools work only in Live 12, while loading stock instruments and Max for Live devices requires the Suite edition【665853537458845†L96-L102】. CLI commands such as `--status`, `--doctor`, `--install` and `--version` simplify installation and diagnostics【665853537458845†L103-L106】.
|
|
12
|
-
|
|
13
|
-
### Project structure and quality
|
|
14
|
-
|
|
15
|
-
Because the repository cannot be cloned from the restricted environment, we rely on the README and manual to infer its structure. The repository contains at least the following components:
|
|
16
|
-
|
|
17
|
-
1. **Remote script (`remote_script/LivePilot`)** – a Python package that subclasses Ableton’s `ControlSurface` class and implements the command queue and handlers. It is installed into Ableton’s User Remote Scripts folder by the `--install` command【692402510651097†L18-L23】.
|
|
18
|
-
2. **MCP server (`mcp_server`)** – a Python server built on the `fastmcp` framework. It validates input parameters (ranges and types) before passing them to the remote script【608977690485721†L29-L34】. Using a single TCP client avoids concurrency issues, because Ableton’s Live Object Model is not thread‑safe【665853537458845†L90-L97】.
|
|
19
|
-
3. **CLI (JavaScript)** – the `npx` entry point uses Node.js to bootstrap the Python server and perform installation tasks. The minimal `requirements.txt` lists `fastmcp` as the only runtime dependency【45077298533394†L0-L2】.
|
|
20
|
-
4. **Docs and tests:** The repo contains a `docs/manual` folder with Markdown documentation, and it mentions a `tests` directory (run by `pytest`)【665853537458845†L110-L111】.
|
|
21
|
-
|
|
22
|
-
While we cannot inspect individual functions, the combination of Python and Node indicates a hybrid architecture. Using `fastmcp` suggests asynchronous I/O and structured validation. The repository emphasises deterministic operations and explicit `undo` functionality【692402510651097†L63-L67】, which points to careful state management. Including a detailed manual and CLI indicates strong attention to developer experience.
|
|
23
|
-
|
|
24
|
-
## Comparison with other AI‑enabled Ableton assistants
|
|
25
|
-
|
|
26
|
-
The AI‑DAW landscape has seen several community‑driven MCP servers that integrate language models with Ableton Live. Below is a comparison of LivePilot with four notable open‑source alternatives and one machine‑learning plugin collection (Magenta Studio). Star counts are ignored; only features matter. All projects implement the MCP for connecting an AI client to Ableton, but they differ in language, feature set and design philosophy.
|
|
27
|
-
|
|
28
|
-
### Feature comparison
|
|
29
|
-
|
|
30
|
-
The table summarises the core capabilities (✓ = present, – = absent or not mentioned). Note: only keywords/phrases are used in the cells; long prose is kept in the explanation below.
|
|
31
|
-
|
|
32
|
-
| Tool/Project | Track & Session management | MIDI/Clip editing | Device/Effect control | Arrangement & automation | Mixing & routing | Browser search | Voice/audio generation | State rollback/Undo | Low‑latency/UDP | Autonomous agent |
|
|
33
|
-
|---|---|---|---|---|---|---|---|---|---|---|
|
|
34
|
-
| **LivePilot (dreamrec)** | create/delete/duplicate tracks, rename, color, mute, solo, arm【665853537458845†L45-L61】 | add/get/modify/duplicate/transpose/quantize notes【665853537458845†L62-L66】 | load instruments/effects, tweak parameters, rack chains, get presets【665853537458845†L66-L69】 | arrangement clip creation & full MIDI note CRUD, cue points, recording, timeline navigation【665853537458845†L74-L81】 | set volume, pan, sends; routing & return tracks; master control【665853537458845†L72-L74】 | search Ableton library & load presets【665853537458845†L72-L75】 | – (not in current version) | deterministic operations with undo/redo commands【692402510651097†L63-L67】 | – | built‑in producer agent via plugin【665853537458845†L82-L89】 |
|
|
35
|
-
| **Ableton Copilot MCP (xiaolaa2)** | create/delete/duplicate/rename MIDI, audio & return tracks; set tempo, time signature and scale【477631886601640†L155-L160】 | add/remove/replace/duplicate notes, filter by pitch, transpose, adjust clip properties【477631886601640†L161-L166】 | browse library, load specific audio effects/instruments/VSTs, modify parameters, record audio into clips【477631886601640†L167-L171】 | – (no dedicated arrangement API mentioned) | – | – | – | robust state management with snapshot & rollback support【477631886601640†L173-L177】 | – | – |
|
|
36
|
-
| **AbletonMCP (ahujasid)** | create/modify MIDI & audio tracks, load and configure remote script【260789399880945†L10-L16】 | create & edit MIDI clips; add notes【260789399880945†L14-L16】【260789399880945†L61-L63】 | select/load instruments & effects from Ableton’s browser【260789399880945†L13-L16】【260789399880945†L61-L63】 | – | basic playback/transport control【260789399880945†L15-L16】 | – | – | – (standard `undo` only) | – | – |
|
|
37
|
-
| **Ableton Live MCP Server (Simon‑Kansara)** | generic track & session control via OSC【308870449054950†L16-L19】 | – | – | – | – | – | – | – | uses UDP/OSC for communication (requires separate daemon)【308870449054950†L30-L34】 | – |
|
|
38
|
-
| **Ableton MCP Extended (uisato)** | comprehensive session & track management including group/folding states【795384148544515†L29-L35】 | create/rename clips; add/delete/transpose/quantize notes; batch edits【795384148544515†L35-L37】 | load instruments/effects; set & batch‑set parameters【795384148544515†L38-L41】 | automation/envelope editing; high‑performance mode using UDP for real‑time control【795384148544515†L41-L54】【795384148544515†L82-L87】 | volume, panning, mute, solo, sends【795384148544515†L29-L35】 | browse Ableton library and import audio files【795384148544515†L44-L46】 | voice/text‑to‑speech integration via ElevenLabs; custom voice & SFX【795384148544515†L47-L50】 | – (standard `undo` not emphasised) | ultra‑low latency via UDP server【795384148544515†L82-L87】 | – |
|
|
39
|
-
| **Magenta Studio (Google)** | – | generates melodies/drums, extends or transforms patterns using ML models【262161962734483†L63-L84】 | – | – | – | – | – | – | – | – |
|
|
40
|
-
|
|
41
|
-
### Discussion
|
|
42
|
-
|
|
43
|
-
#### Breadth of control
|
|
44
|
-
|
|
45
|
-
LivePilot stands out for its broad coverage of Ableton’s API. It not only performs basic track and session operations but also supports **arrangement view editing** (creating arrangement clips, moving between cue points, starting/stopping recording, editing automation)【665853537458845†L74-L81】. Most competitors focus on session view; for example, Ableton Copilot MCP’s documentation highlights track/clip manipulation and device control but does not mention arrangement or automation【477631886601640†L155-L171】. AbletonMCP Extended adds some automation editing and envelope functionality【795384148544515†L41-L46】 but still doesn’t provide the same comprehensive list of arrangement tools.
|
|
46
|
-
|
|
47
|
-
#### Mixing and browser integration
|
|
48
|
-
|
|
49
|
-
LivePilot provides dedicated mixing tools (volume, pan, sends, routing, return tracks and master volume)【665853537458845†L72-L74】 and separate browser tools to search the entire Ableton library and load presets【665853537458845†L72-L75】. The other projects have limited mixing commands; AbletonMCP Extended includes volume/panning/mute/solo and send control【795384148544515†L29-L35】, but others do not emphasise mixing. Browser search appears in LivePilot and Extended; it is absent from Copilot MCP.
|
|
50
|
-
|
|
51
|
-
#### Safety and robustness
|
|
52
|
-
|
|
53
|
-
LivePilot emphasises deterministic operations and encourages the AI to verify the session state after every write. The `undo` tool is exposed, making all destructive operations reversible【692402510651097†L63-L67】. Ableton Copilot MCP goes further with **state rollback**; it snapshots the project state and can undo groups of operations, which is a robust safety net for complex tasks【477631886601640†L173-L177】. Competitors built on Python sockets generally rely on Ableton’s own undo (a single step), so LivePilot’s explicit undo tool is a strength but could be improved by adopting a snapshot approach.
|
|
54
|
-
|
|
55
|
-
#### Advanced features
|
|
56
|
-
|
|
57
|
-
* **Autonomous agent:** LivePilot’s Claude plug‑in includes a **producer agent** that builds complete tracks from high‑level descriptions【665853537458845†L82-L89】. None of the other open‑source projects advertise an autonomous composition agent, although some AI‑first DAW assistants outside the MCP ecosystem (e.g., commercial “Studio Co‑Pilot” or online generative services) may offer similar features.
|
|
58
|
-
* **Voice and audio generation:** Ableton MCP Extended uniquely integrates ElevenLabs for voice/speech generation and allows direct import of generated audio into Ableton sessions【795384148544515†L47-L50】. LivePilot lacks this type of generative audio; adding a similar feature could broaden its creative scope.
|
|
59
|
-
* **Low‑latency control:** The Extended project includes a UDP server for ultra‑low‑latency parameter control【795384148544515†L82-L87】. LivePilot uses a single TCP connection for thread safety【665853537458845†L90-L97】; while stable, it may introduce latency for real‑time performance. Offering a high‑performance mode or MIDI mapping could appeal to live performers.
|
|
60
|
-
* **State management:** Ableton Copilot MCP’s snapshot‑based rollback system is a notable innovation【477631886601640†L173-L177】. LivePilot currently supports standard undo/redo but not multi‑step rollback; implementing such a feature would increase safety.
|
|
61
|
-
* **Extensibility:** Both LivePilot and Ableton MCP Extended provide frameworks for creating custom tools. LivePilot’s skill file teaches the AI how to interact correctly【692402510651097†L69-L81】, and the Extended project demonstrates building custom controllers (XY mouse controller)【795384148544515†L82-L87】.
|
|
62
|
-
|
|
63
|
-
#### Installation and user experience
|
|
64
|
-
|
|
65
|
-
LivePilot provides a simple `npx` installer and CLI commands to install, check status and run diagnostics【665853537458845†L22-L27】【665853537458845†L103-L106】. Ableton Copilot MCP similarly offers one‑line installation via `npx @xiaolaa2/ableton-copilot-mcp --install-scripts`【477631886601640†L213-L216】. AbletonMCP and Extended require cloning or using `uv` and copying remote scripts manually【260789399880945†L21-L34】【795384148544515†L56-L66】, which is less streamlined. LivePilot’s documentation is thorough and includes a manual covering workflows, whereas competitors often rely on README‑level documentation or blog posts.
|
|
66
|
-
|
|
67
|
-
### Strengths and areas for improvement
|
|
68
|
-
|
|
69
|
-
#### Strengths of LivePilot
|
|
70
|
-
|
|
71
|
-
1. **Comprehensive toolset:** With 91 tools covering transport, track management, clip operations, note editing, devices, scenes, mixing, browser search and arrangement, LivePilot offers the broadest feature coverage among existing MCP servers【665853537458845†L43-L70】.
|
|
72
|
-
2. **Natural‑language workflows:** The manual demonstrates how to use conversation to build beats, search for instruments, program MIDI patterns and mix tracks【692402510651097†L39-L51】. This conversational approach, combined with the producer agent, makes LivePilot accessible to users with minimal technical knowledge.
|
|
73
|
-
3. **Deterministic operations and safety:** By mapping tools directly to Ableton’s API and exposing undo/redo, LivePilot aims to provide predictable outcomes and a clear safety net【608977690485721†L23-L27】【692402510651097†L63-L67】.
|
|
74
|
-
4. **Developer experience:** The `npx` installer, CLI commands (`--status`, `--doctor`), cross‑platform support (macOS and Windows) and extensive manual contribute to a polished user experience【665853537458845†L103-L106】.
|
|
75
|
-
5. **Plugin & agent integration:** The Claude plug‑in adds slash commands and an autonomous producer agent that can compose full tracks from high‑level prompts【665853537458845†L82-L89】. This is unique among open‑source MCP servers.
|
|
76
|
-
|
|
77
|
-
#### Areas for improvement
|
|
78
|
-
|
|
79
|
-
1. **State rollback and history:** Competing projects like Ableton Copilot MCP implement snapshot‑based rollback【477631886601640†L173-L177】. Incorporating multi‑step undo or versioned snapshots in LivePilot would improve safety during complex editing.
|
|
80
|
-
2. **Voice and audio generation:** Ableton MCP Extended integrates ElevenLabs for text‑to‑speech and can import generated vocals or sound effects【795384148544515†L47-L50】. Adding optional integration with generative audio tools (e.g., ElevenLabs, OpenAI TTS) could expand LivePilot’s creative capabilities.
|
|
81
|
-
3. **Low‑latency control:** The Extended project’s UDP server provides ultra‑low‑latency parameter control【795384148544515†L82-L87】. LivePilot could explore a similar performance mode or integration with hardware controllers to better serve live performers.
|
|
82
|
-
4. **Simplify cross‑language architecture:** LivePilot uses Node.js to bootstrap a Python server; although this is hidden from the user, consolidating components or providing a purely Python installation could reduce complexity and dependency on Node.
|
|
83
|
-
5. **Community engagement:** Many competing projects have active communities and Discord servers (e.g., AbletonMCP invites feedback on Discord【260789399880945†L8-L9】). Building a community around LivePilot would encourage contributions, gather feedback and accelerate development.
|
|
84
|
-
|
|
85
|
-
## Conclusion
|
|
86
|
-
|
|
87
|
-
LivePilot is an ambitious and well‑documented project that aims to be a **comprehensive AI co‑pilot** for Ableton Live 12. Its strength lies in its broad tool coverage, polished installation experience, deterministic operations and the inclusion of a plug‑in with an autonomous producer agent. Compared with other MCP servers, LivePilot covers more domains (especially arrangement and mixing) and provides a more polished user experience. Competing projects offer innovations such as state rollback, voice/audio generation and low‑latency control. Incorporating similar features, encouraging community engagement and potentially simplifying the architecture would enhance LivePilot’s position as the most intelligent and versatile AI assistant for Ableton Live.
|