Observed since 20 Oct, 17:29 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
ableton-mcp-suite
Heavily extended Ableton Live integration via MCP — 45 tools (vs 16 upstream) for device parameters, sidechain routing, arrangement view, return/master tracks, audio import, and clip editing from Claude
A heavily extended fork of @ahujasid/ableton-mcp — 45 tools total (22 new + 10 enhanced) for full music production workflows from Claude.
The upstream ableton-mcp exposes 16 mostly-additive tools (create track, create clip, add notes, fire/stop, set tempo). This fork adds device parameter control, track state management, audio import, return/master track support, full Arrangement view operations, device routing (sidechain!), and locator/cue point management — everything you need to take Claude from "writes MIDI notes" to "actually mixes and arranges a song."
Every tool in this fork was added during a real production session (a 12+ hour Afro-deep-house track build), in response to a real blocker. Nothing is speculative.
Upstream ableton-mcp is a brilliant bridge — it solves the hard problem of connecting Claude to Ableton via a Remote Script + socket server. But its surface is narrow:
This fork addresses all of the above with 22 new tools plus enhancements to 10 existing tools.
uv package manager# Clone this fork
git clone https://github.com/farmhutsoftwareteam/ableton-mcp-extended.git
cd ableton-mcp-extended
⚠️ On Ableton Live 12, install the Remote Script at:
~/Music/Ableton/User Library/Remote Scripts/AbletonMCP/__init__.py
NOT the path the upstream README suggests (User Remote Scripts under Preferences — that's for Instant Mappings, not full Remote Scripts). This is a Live 12 change that the upstream README hasn't been updated for.
mkdir -p "$HOME/Music/Ableton/User Library/Remote Scripts/AbletonMCP"
cp AbletonMCP_Remote_Script/__init__.py "$HOME/Music/Ableton/User Library/Remote Scripts/AbletonMCP/__init__.py"
On Windows, the path is %USERPROFILE%\Documents\Ableton\User Library\Remote Scripts\AbletonMCP\__init__.py.
AbletonMCPIf "AbletonMCP" doesn't appear in the dropdown, fully quit Live (⌘Q / Alt-F4) and reopen — Remote Scripts are only scanned on startup.
For Claude Desktop, edit ~/Library/Application Support/Claude/claude_desktop_config.json (Mac) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"ableton-mcp": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/ableton-mcp-extended", "python", "-m", "MCP_Server.server"]
}
}
}
For Claude Code (CLI):
claude mcp add ableton-mcp -s user -- uv run --directory /absolute/path/to/ableton-mcp-extended python -m MCP_Server.server
Restart your Claude client. You should see ableton-mcp connected with 38 tools available.
Legend: 🆕 = new in this fork · ⊕ = enhanced (extra parameters) · ✅ = unchanged from upstream
| Tool | Notes |
|---|---|
get_session_info() | ✅ Tempo, signature, track count, master |
get_track_info(track_index, track_kind="regular") | ⊕ track_kind parameter — "regular", "return", "master" |
get_master_track_info() 🆕 | Convenience — no index needed |
get_browser_tree(category_type="all") | ✅ Hierarchical browser tree |
get_browser_items_at_path(path) | ✅ List items at a specific browser path |
| Tool | Notes |
|---|---|
create_midi_track(index=-1) | ✅ Create new MIDI track |
create_audio_track(index=-1) 🆕 | Create new audio track |
set_track_name(track_index, name, track_kind="regular") | ⊕ Now supports returns + master |
set_track_volume(track_index, volume, track_kind="regular") 🆕 | 0.0–1.0 (0.85 ≈ unity) |
set_track_pan(track_index, pan, track_kind="regular") 🆕 | -1.0 (L) to 1.0 (R) |
set_track_send(track_index, send_index, value) 🆕 | 0.0–1.0; sends to return tracks |
set_track_mute(track_index, mute, track_kind="regular") 🆕 | Bool — works on regulars + returns |
set_track_solo(track_index, solo, track_kind="regular") 🆕 | Bool |
set_track_arm(track_index, arm) 🆕 | Bool — regulars only |
delete_track(track_index) 🆕 | Destructive, no undo on trial license |
| Tool | Notes |
|---|---|
create_clip(track_index, clip_index, length=4.0) | ✅ Create empty MIDI clip |
set_clip_name(track_index, clip_index, name) | ✅ Rename clip |
add_notes_to_clip(track_index, clip_index, notes) | ✅ Write MIDI notes |
delete_clip(track_index, clip_index) 🆕 | Remove clip from Session slot |
import_audio_file(track_index, clip_index, file_path) 🆕 | Load audio file. Multiple fallback strategies — direct API, browser refresh, walk all browser attributes. Documents API limitations honestly. |
fire_clip(track_index, clip_index) | ✅ Fire (play) a Session clip |
stop_clip(track_index, clip_index) | ✅ Stop a Session clip |
| Tool | Notes |
|---|---|
load_instrument_or_effect(track_index, uri, track_kind="regular") | ⊕ Load device on regular / return / master |
load_drum_kit(track_index, rack_uri, kit_path) | ✅ Load drum rack + kit |
get_device_parameters(track_index, device_index, track_kind="regular") 🆕 | List every parameter with name, current value, min, max, quantized values |
set_device_parameter(track_index, device_index, parameter_index, value, track_kind="regular") 🆕 | The big one — dial any knob |
delete_device(track_index, device_index, track_kind="regular") 🆕 | Remove device from chain |
get_device_routings(track_index, device_index, track_kind="regular") 🆕 | Inspect available input routings (sidechain sources, etc.) |
set_device_routing(track_index, device_index, routing_type_name, routing_channel_name, track_kind="regular") 🆕 | Set sidechain input / device routing |
| Tool | Notes |
|---|---|
place_clip_in_arrangement(track_index, source_slot, position) 🆕 | Duplicate a Session MIDI clip onto the timeline at a beat position |
clear_arrangement_clips(track_index) 🆕 | Delete all arrangement clips on a track |
get_arrangement_clips(track_index) 🆕 | List arrangement clips with positions/lengths/names |
set_locator(position, name) 🆕 | Add or update a named locator (cue point) |
clear_locators() 🆕 | Delete all locators |
set_loop(start, length, enabled=True) 🆕 | Set Arrangement view loop region |
| Tool | Notes |
|---|---|
start_playback() | ✅ Start playback |
stop_playback() | ✅ Stop playback |
set_tempo(tempo) | ✅ Set song tempo |
Total: 38 tools.
This fork was built in a single ~12-hour production session, alongside the actual music it was being used to make ("Mbira Tension Stems" — an Afro-deep-house track combining Suno-generated stems with original Ableton MIDI). Every tool was added in direct response to a real production blocker. The fork evolved across five versions:
Blocker: Claude could load a Reverb but couldn't set its decay. Could create tracks but couldn't mute or solo them.
Added: get_device_parameters, set_device_parameter, set_track_volume, set_track_mute, set_track_solo, set_track_arm, delete_track, delete_clip, delete_device.
The single biggest unlock was set_device_parameter — turning Claude from "load default devices" into "dial in actual settings." Suddenly we could specify "set Compressor attack to 0.5ms, ratio to 4:1" and have it happen.
Blocker: Couldn't create audio tracks. Couldn't set pan or sends. Couldn't import audio files.
Added: create_audio_track, set_track_pan, set_track_send, import_audio_file.
import_audio_file is the gnarly one. Live's Python API doesn't accept arbitrary file paths directly — files have to be reachable through Live's browser. The implementation walks the browser tree looking for a match, with multiple fallback strategies and honest error messages when it can't find the file. This is documented as a known limitation.
Blocker: Couldn't put reverb on a return track. Couldn't load a limiter on master.
Realized Live distinguishes _song.tracks, _song.return_tracks, and _song.master_track — three separate collections. Added an optional track_kind parameter ("regular", "return", "master") to 10 existing tools (get_track_info, set_track_name, set_track_volume, set_track_pan, set_track_mute, set_track_solo, load_instrument_or_effect, get_device_parameters, set_device_parameter, delete_device). Plus added get_master_track_info() as a convenience.
Blocker: All clips landed in Session view. Building a song timeline meant dragging every clip manually onto Arrangement.
Added: place_clip_in_arrangement, clear_arrangement_clips, get_arrangement_clips, set_locator, set_loop.
place_clip_in_arrangement reads notes from a Session MIDI clip (via clip.get_notes_extended()), creates a new clip on the Arrangement timeline via track.create_midi_clip(start, end), then writes the notes into it. This let us programmatically construct a 120-bar song timeline with 186 clip placements in two batches of MCP calls.
Bugs found in v4:
get_notes_extended() returns tuples, not objects. My first implementation assumed it returned MidiNote objects with .pitch attributes — it actually returns tuples (pitch, time, duration, velocity, mute). Fixed to handle all three shapes (tuples, objects, dicts).
current_song_time can't be set past song length. Live refused to position the playhead at beat 192 when the song was only 0 bars long. The locator API requires moving the playhead first. Fixed with a song-length pre-check + clearer error message. Workaround: place arrangement clips first to extend the song, then add locators.
Added: clear_locators() for redo workflows.
Blocker: Couldn't set sidechain inputs on Compressors. This is THE deep-house signature — kick triggers bass + pads ducking. Without it, the mix doesn't breathe.
Realized Live distinguishes "parameters" (continuous knob values) from "routings" (channel source selections). set_device_parameter only handles parameters. Sidechain INPUT is a routing.
Added: get_device_routings, set_device_routing. They probe multiple Live API surfaces (available_input_routing_types, input_routing_types, input_routings, audio_inputs) because the property names vary across Live versions, and return diagnostic info on failure.
get_notes_extended() returns tuples on Live 12.4 Beta, not objects. The implementation handles tuples, objects with .pitch, and dicts.current_song_time can't be set past song length. Locator placement validates against song length first; gives a clear error message pointing to the fix (place clips first).import_audio_file tries multiple fallbacks: direct clip_slot.create_audio_clip(path), app.browser.refresh(), walks all browser attributes via dir().set_device_routing) with its own discovery flow (get_device_routings)._song.tracks, _song.return_tracks, _song.master_track are three different collections. The track_kind parameter dispatches correctly.All commands that modify Live state are scheduled on Live's main thread via self.schedule_message(0, main_thread_task). Read-only commands (get_session_info, browser inspection) run directly. This matches the upstream pattern.
Every tool returns rich diagnostic info on failure — what was tried, what was available, what the Live API surfaced. Production sessions hit unfamiliar API surfaces constantly; clear errors save hours.
clip.envelopes API which isn't exposed in this fork. Coming in a future version.~/Music/Ableton/User Library/ or a folder added as a Place in Live's browser sidebar. The browser-walk implementation can find them only after Live has indexed them.ableton, ableton live, ableton 12, ableton 11, ableton mcp, ableton remote script, ableton python api, live object model, model context protocol, mcp, claude, claude code, claude desktop, anthropic, anthropic mcp, ai music, ai music production, ai daw, ai assisted music, generative music, prompt music production, deep house, afro house, deep house production, midi, midi automation, ableton automation, ableton sidechain, ableton arrangement, ableton routing, daw automation, mbira, zimbabwean music, kalimba, claude ableton, ableton plugin, ableton extension, music ai tools, mixing, mastering, ableton scripting, live api python, max for live alternative, ableton remote control, ableton tooling, ableton developer
Built on top of @ahujasid/ableton-mcp by Siddharth Ahuja. All credit for the original Remote Script framework + socket bridge + initial tool set goes there.
Extensions in this fork by farmhutsoftwareteam (Munya Makosa), built during production of the Mbira Tension Stems project. Pull requests welcome.
MIT (same as upstream).
Found a Live API quirk this fork doesn't handle? Want to add automation envelopes, vocal-chop importing, M4L device control, or any of the other missing pieces? PRs welcome. Open an issue first if it's a big change.
The codebase is small and well-documented — AbletonMCP_Remote_Script/__init__.py is the Remote Script (lives inside Live), MCP_Server/server.py is the MCP server (talks to Claude). Each tool follows a simple pattern: add the command_type to the dispatch list, add an elif handler, add an implementation method, add a matching @mcp.tool() in the server.
This is an unofficial third-party integration. Not affiliated with or endorsed by Ableton.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
mcpEnvironment{
"extras": "cli",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | mcp[cli]>=1.3.0 | runtime |
bdist_wheel · 18.59 KB · Python py3
sdist · 18.82 KB · Python source
Shared repository data · GitHub
Observed since 20 Oct, 17:29 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:5cbd4a0d01d4f5c03a5df9563de6fce4e2e5c07a1445fb509cb734e2ccac231a