ableton12-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ableton12-mcp Set the master volume to -3 dB and analyze the loudness"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ableton12 — full-control MCP server for Ableton Live 12
A Python + uv MCP server that lets an LLM (Claude Code,
Claude Desktop, any MCP client) drive Ableton Live 12 through the Live Object Model —
and, uniquely, measure what it just made.
It is a drop-in superset of the upstream
ahujasid/ableton-mcp: it keeps the 16 original tools
(identical names, params and return values, so existing prompts/permissions keep working) and adds
everything upstream can't do — 62 tools in total:
Device & instrument parameter control — read every parameter and actually change the tone: filter cutoff, oscillator type, reverb decay, macros, device bypass.
Mixer — volume, pan, sends, mute, solo, arm, color. Addresses the master bus and return tracks, not just regular tracks.
Tracks / clips / scenes / transport — create audio & return tracks, read & remove notes, loop settings, duplicate, delete, color, fire scenes, time signature, metronome, playhead.
Session → Arrangement capture — record a Session scene into the Arrangement so Live's exporter (Arrangement-only) can render it.
Ears — capture any single track (or the master / a return) to a WAV via a loopback device and analyze it: LUFS, true peak, 10-band spectrum, spectral centroid, transient punch, stereo width. Plus
compare_audiofor before/after A-B of a parameter change. This is what makes an autonomous measure → adjust → re-measure tuning loop possible instead of guessing.Host automation (macOS) — launch Live, new Set, Save, Save As, open the Export dialog.
Scope: this repo is the MCP server + Remote Script only. The composition prompt-layer built on top of it (slash commands like
/clip,/master,/dial,/export) lives elsewhere; every tool here is usable from any MCP client on its own.
Architecture
Two halves talk over TCP localhost:9877 using 4-byte length-prefixed JSON frames:
LLM ⇄ (stdio) ⇄ ableton12 MCP server ⇄ (TCP 9877) ⇄ Remote Script (inside Live)
src/ableton12_mcp/ remote_script/AbletonMCP/
│
└─ ffmpeg + loopback device ─► WAV ─► analysis (numpy/scipy/pyloudnorm)MCP server (
src/ableton12_mcp/server.py): FastMCP server namedAbletonMCP. Each@mcp.tool()sends one command frame and returns the result._host.pydoes the macOS-level automation,_record.pythe loopback capture,_analysis.pythe audio metrics.Remote Script (
remote_script/AbletonMCP/__init__.py): aControlSurfacerunning inside Live's embedded Python. A socket thread does pure I/O; every command — reads included — is marshaled onto Live's main thread viaschedule_message+ a reply queue (_run_on_main). That is the key correctness fix: upstream's device-parameter attempts crashed because reads ran off the main thread while writes ran on it.
Related MCP server: io.github.peterkolbe/ableton-for-ai
Requirements
Ableton Live 12 | the Remote Script targets Live 12's Object Model |
macOS | required for host automation ( |
Python ≥ 3.10 + |
|
ffmpeg (optional) | needed by |
BlackHole (optional) | loopback device for the "ears" — |
Install
# 1. Clone and sync dependencies
git clone https://github.com/verove-jordan/ableton12-mcp.git
cd ableton12-mcp
uv sync
# 2. Install the Remote Script into Ableton's User Library
# (quit Live first; the script backs up any existing AbletonMCP install)
./install.sh
# 3. In Ableton: Settings → Link, Tempo & MIDI → Control Surfaces → pick "AbletonMCP"
# with Input = None and Output = None, then RESTART Ableton.
# The status bar should read: AbletonMCP (ableton12): listening on port 9877
# 4. Register the server with your MCP client — e.g. Claude Code, at user scope:
claude mcp add AbletonMCP -s user -- uvx --from "$(pwd)" ableton12
# Then run /mcp to connect and call the `health` tool to verify.Generic MCP client config (Claude Desktop, .mcp.json, …) — use an absolute path:
{
"mcpServers": {
"AbletonMCP": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "/absolute/path/to/ableton12-mcp", "ableton12"]
}
}
}Only one process may bind port 9877 — make sure no old uvx ableton-mcp server is still running.
Optional: the "ears" (per-track capture)
record_audio records Live's output in realtime from a loopback audio input, so you need one:
brew install ffmpeg blackhole-2chAudio MIDI Setup → create a Multi-Output Device containing both your speakers/ headphones and BlackHole; set it as Live's output (Preferences → Audio) or the system output — that way you still hear playback while it is captured.
macOS will prompt once for Microphone access for the app running the MCP server (capturing an audio input counts as mic use): System Settings → Privacy & Security → Microphone.
Capture is realtime — a window's wall-clock equals its musical length, so keep windows short (2–4 bars).
Optional: host automation permissions
save_set_as and open_export_dialog drive Live's menus with AppleScript keystrokes, which needs a
one-time Accessibility grant for the app running the MCP server (Terminal / iTerm / your editor):
System Settings → Privacy & Security → Accessibility. These routines are best-effort and depend on
the running Live version's dialog layout — always verify the resulting file on disk rather than
trusting the return value.
Tool catalog (62)
Session & transport: get_session_info, set_tempo, start_playback, stop_playback,
set_time_signature, set_metronome, set_song_position, get_transport, health.
Tracks: get_track_info, create_midi_track, create_audio_track, create_return_track,
set_track_name, delete_track, duplicate_track.
Mixer: set_track_volume, set_track_pan, set_track_send, set_track_mute,
set_track_solo, set_track_arm, set_track_color.
Devices & parameters: get_device_parameters, set_device_parameter, set_device_enabled,
delete_device, get_macros, set_macro.
Browser / loading: get_browser_tree, get_browser_items_at_path, load_instrument_or_effect,
load_drum_kit.
Clips: create_clip, add_notes_to_clip, get_clip_notes, remove_notes_from_clip,
set_clip_name, set_clip_loop, duplicate_clip, delete_clip, set_clip_color, fire_clip,
stop_clip.
Scenes: create_scene, fire_scene, set_scene_name, delete_scene.
Session → Arrangement capture: set_arrangement_record, set_clip_trigger_quantization,
capture_session_to_arrangement.
Metering: get_track_meter, get_master_meter (levels 0..1, only while playing).
Listening & analysis: record_audio, record_and_analyze, analyze_audio, compare_audio.
Host automation (macOS): launch_ableton, new_live_set, save_set, save_set_as,
open_export_dialog.
Addressing the master bus and return tracks
Track-scoped tools (get_track_info, load_instrument_or_effect, get_device_parameters,
set_device_parameter, set_device_enabled, delete_device, set_track_volume, set_track_pan,
get_track_meter, record_audio, …) take an optional track argument that overrides the
integer track_index:
track='master'→ the master bus (this is how you build a mastering chain),track='return:0'→ return track 0 (return:N), fed byset_track_send.
Plain integer track_index calls are unchanged.
Parameter value semantics (read this before "changing the tone")
get_device_parameters(track, device) returns each parameter with name, value, min, max,
is_quantized, value_items (enum labels) and display_value (e.g. "440 Hz", "Lowpass").
Always read before you write — ranges are device- and install-specific. Then
set_device_parameter:
Continuous params: pass
valuein native units (within[min, max]), orvalue_normalized(0..1 →min + x*(max-min)). Values are clamped.Quantized params (
is_quantized=true): passvalueas either the integer index or the exactvalue_itemslabel (case-insensitive), orvalue_normalizedto pick by fraction.A parameter mapped to a macro reports
is_enabled=false; writes to it are skipped and the reply says so (applied=false). Change it through the macro (set_macro) instead.
Mixer ranges: volume is a fader position 0..1, not dB (~0.85 ≈ 0 dB, 1.0 ≈ +6 dB — the reply reports the resulting dB). Pan is −1..+1. Sends are 0..1.
Typical workflow: load_instrument_or_effect → get_device_parameters → set_device_parameter.
After structural edits (delete_track, create_*, delete_scene) re-read get_session_info,
because indices shift.
What analyze_audio returns
Peak/RMS dBFS, crest factor, clipping; LUFS (lufs_integrated, lufs_short_term_max,
lufs_range_lra) and true peak (true_peak_dbtp); a 10-band spectrum (spectrum_bands /
spectrum_bands_db) plus a legacy 4-band; brightness (spectral_centroid_hz,
spectral_rolloff_hz, spectral_flatness); transients (onset_strength, onset_rate_per_sec,
band_crest_db per band — low-band crest ≈ kick punch); stereo (stereo_correlation,
stereo_width, band_stereo_width); plus noise floor, DC offset and silence detection.
loudness_method flags whether pyloudnorm or the numpy fallback produced the LUFS figures.
compare_audio(a, b) turns two of those into per-metric deltas in human terms with a one-line
headline, suppressing sub-perceptual changes — the progress meter for a tuning loop.
Known limitation — no automation over time
The server can set a parameter to a static value, but it cannot write clip/device automation
envelopes, so moves that evolve across an arrangement (a filter opening over 16 bars, a
progressive L↔R pan sweep) are not directly authorable. Workarounds and the plan to close the gap
are in docs/AUTOMATION_TODO.md.
Debugging
"Connection refused" / can't connect: Ableton isn't running, wasn't restarted after a script change, or the control surface isn't selected. Don't retry blindly — check those three.
Confirm Live holds the port:
lsof -nP -iTCP:9877 -sTCP:LISTENshould showLive. If it shows apython/uvxprocess, a stale server has the port.Remote Script logs:
~/Library/Preferences/Ableton/Live 12*/Log.txt— look forAbletonMCP (ableton12) ... initializingandlistening on port. Useself.log_message;print()from the script is invisible.After editing the Remote Script you must restart Ableton (or re-select the control surface).
install.shclears__pycache__; thehealthtool reports the loaded version so you can confirm the new build is active.
Credits
API-compatible with, and inspired by, ahujasid/ableton-mcp.
Not affiliated with Ableton AG.
Available Tools
62 toolsadd_notes_to_clipA
Add MIDI notes to a clip (additive — call repeatedly to build large clips).
Each note dict: pitch (0-127), start_time (beats), duration (beats),
velocity (1-127), mute (bool, optional).Inputs: notes (required), clip_index (required), track_index (required). Returns: result
analyze_audioA
Analyze a rendered/captured audio file — the objective 'listening' step.
Returns peak/RMS dBFS, crest factor, clipping; LUFS (integrated/short-term/
LRA) and true peak (dBTP); a 10-band spectrum (+ legacy 4-band) with centroid,
rolloff and flatness; transient/punch (onset strength/rate, per-band crest);
stereo correlation + overall/per-band width; DC offset, noise floor and
leading/trailing silence. `loudness_method` says whether LUFS came from
pyloudnorm or the numpy fallback. Capture a track/section first (record_audio)
or render via the export path, then analyze. Needs numpy+soundfile.Inputs: wav_path (required). Returns: result
capture_session_to_arrangementA
Record a Session scene into the Arrangement so the song can be exported.
Live's Export Audio/Video only renders the Arrangement, so a Session-view
loop must first be printed there. This automates the whole capture — no
manual Arrangement-record arming:
1. stop, rewind to 1.1.1, force Session Record off, and (if tighten_launch)
set clip-launch quantization to None for a tight start at bar 1,
2. arm Arrangement Record (the ● button),
3. fire scene `scene_index` — its clips begin printing into the Arrangement,
4. wait one full pass (`length_beats` + `tail_beats`), polling the playhead,
5. stop, disarm record, restore quantization, rewind, return to Arrangement.
length_beats = bars * time_signature_numerator (e.g. 128 bars of 4/4 = 512).
`tail_beats` lets the final notes ring before stopping. Re-recording the same
span overwrites the previously captured Arrangement region for the scene's
tracks, so re-exports stay clean.
wait=True (default) blocks until the pass finishes and returns the result.
wait=False arms + fires and returns immediately (then call stop_playback and
set_arrangement_record(False) yourself once the playhead reaches length_beats).
max_wait_seconds caps the blocking wait (0 = auto: one pass + 15 s headroom).Inputs: scene_index (required), length_beats (required), wait, tail_beats, +2 more. Returns: result
compare_audioA
Diff two audio files (b relative to a) into human-readable deltas — loudness, per-band level, brightness (centroid), punch (low-band crest), width and dynamics, plus a one-line headline. Sub-perceptual changes are suppressed. This is the closed loop's progress meter: capture before/after a parameter move and compare to confirm the change helped.
Inputs: path_a (required), path_b (required). Returns: result
create_audio_trackB
Create a new audio track. index=-1 appends at the end.
Inputs: index. Returns: result
create_clipA
Create a new empty MIDI clip. length is in BEATS (not bars).
Inputs: clip_index (required), track_index (required), length. Returns: result
create_midi_trackA
Create a new MIDI track. index=-1 appends at the end. Re-read get_session_info afterwards to learn the real new index.
Inputs: index. Returns: result
create_return_trackA
Create a new return track (appended after existing returns).
Inputs: no named parameters. Returns: result
create_sceneA
Create a new scene. index=-1 appends at the end.
Inputs: index. Returns: result
delete_clipB
Delete the clip in a clip slot.
Inputs: clip_index (required), track_index (required). Returns: result
delete_deviceB
Delete a device from a track. track='master'/'return:N' targets those tracks.
Inputs: track_index (required), device_index (required), track. Returns: result
delete_sceneA
Delete a scene. Higher scene indices shift down.
Inputs: scene_index (required). Returns: result
delete_trackA
Delete a track. All higher track indices shift down — re-read get_session_info afterwards.
Inputs: track_index (required). Returns: result
duplicate_clipB
Duplicate a clip into the next clip slot on the same track.
Inputs: clip_index (required), track_index (required). Returns: result
duplicate_trackA
Duplicate a track (with its devices and clips). Re-read get_session_info afterwards to learn indices.
Inputs: track_index (required). Returns: result
fire_clipB
Start playing a clip (launches the clip slot).
Inputs: clip_index (required), track_index (required). Returns: result
fire_sceneA
Launch a scene (fires every track's clip in that scene row).
Inputs: scene_index (required). Returns: result
get_browser_items_at_pathA
List browser items at a path like 'instruments/Operator' or 'drums'. Each item reports name, is_folder, is_loadable and uri.
Inputs: path (required). Returns: result
get_browser_treeA
Get the top-level browser categories ('all', 'instruments', 'sounds', 'drums', 'audio_effects', 'midi_effects'). Use get_browser_items_at_path to drill in and find loadable URIs.
Inputs: category_type. Returns: result
get_clip_notesA
Read all MIDI notes from a clip. Returns JSON with a list of notes (pitch, start_time, duration, velocity, mute, and note_id when available).
Inputs: clip_index (required), track_index (required). Returns: result
get_device_parametersA
List every automatable parameter of a device on a track.
Returns JSON with the device name and a list of parameters, each:
index, name, value, min, max, is_quantized, value_items (enum labels for
quantized params, else null), display_value (e.g. '440 Hz', 'Lowpass'),
default_value, is_enabled. Use this to discover what you can change, then
call set_device_parameter. track='master'/'return:N' targets those tracks.Inputs: track_index (required), device_index (required), track. Returns: result
get_macrosA
List the macro controls of a Rack device (Instrument/Audio/MIDI/Drum Rack). Returns JSON like get_device_parameters but limited to the rack's macros. Set them with set_macro (or set_device_parameter).
Inputs: track_index (required), device_index (required). Returns: result
get_master_meterA
Read the master bus output meter (0..1). Sample while a scene is playing to gauge overall level / spot clipping (level near 1.0 = too hot).
Inputs: no named parameters. Returns: result
get_session_infoA
Get detailed information about the current Ableton session (tempo, time signature, track/return/scene counts, master mixer).
Inputs: no named parameters. Returns: result
get_track_infoA
Get detailed info about a track: name, mute/solo/arm, volume/pan, clip slots, and the ordered list of devices (with their indices).
Pass track='master' or track='return:0' to inspect the master bus or a
return track (those have no clip slots).Inputs: track, track_index. Returns: result
get_track_meterA
Read a track's output meter (0..1) for left/right and overall level. track can be an int index, 'master', or 'return:N'. Meters only move while audio plays — fire a clip/scene first, then sample (call a few times).
Inputs: track. Returns: result
get_transportA
Report transport/record state: is_playing, record_mode (Arrangement Record ● armed?), session_record, current_song_time (beats), back_to_arranger, clip_trigger_quantization, tempo and time signature. Use it to verify a capture is running and to watch the playhead advance.
Inputs: no named parameters. Returns: result
healthA
Diagnostic: confirm the connection and report the Remote Script version that is actually loaded in Ableton (useful after reinstalling the script).
Inputs: no named parameters. Returns: result
launch_abletonA
Launch (or focus) Ableton Live 12, optionally opening a .als, then wait for the AbletonMCP control-surface bridge to come up on :9877. Use this to start Ableton before composing, or to reopen a saved project.
Inputs: als_path. Returns: result
load_drum_kitB
Load a Drum Rack, then load the first loadable kit found at kit_path.
Inputs: kit_path (required), rack_uri (required), track_index (required). Returns: result
load_instrument_or_effectA
Load an instrument or effect device onto a track by its browser URI.
Discover URIs with get_browser_tree / get_browser_items_at_path. After
loading, use get_device_parameters + set_device_parameter to dial it in.
Pass track='master' or track='return:0' to load onto the master bus or a
return track (e.g. a Reverb on a return, or the master-bus chain).Inputs: uri (required), track_index (required), track. Returns: result
new_live_setA
File ▸ New Live Set (Cmd-N) for a clean slate. The control surface is a global preference, so the :9877 bridge survives. Requires Accessibility.
Inputs: no named parameters. Returns: result
open_export_dialogA
Open Export Audio/Video (Cmd-Shift-R) and copy target_path to the clipboard for pasting into the save sheet. Returns the remaining steps; does NOT press Render (you confirm the export). Requires Accessibility.
Inputs: format_hint, target_path. Returns: result
record_and_analyzeA
Capture source (see record_audio) then analyze it in one call — the
single primitive the tuning loop uses: change a parameter, then
record_and_analyze(source=track, bars=2, scene=N) to read the result.
Returns {capture, analysis}.
Inputs: bars, solo, scene, device, +3 more. Returns: result
record_audioA
Capture Live's audio output to a WAV via a loopback device (BlackHole) —
the per-track 'ears'. Give a duration as bars (resolved from the session
tempo/meter) or seconds; capture is REALTIME so prefer 2–4 bars.
source: a track index (int) to capture ONE track — it is soloed for the
capture and the prior solo state is restored — or 'master' / 'return:N'
(no solo). scene: the Session scene to fire so clips actually play (this
project composes in Session view — pass the arrangement scene index);
omit scene to play the Arrangement from position_beats instead.
Needs BlackHole + a Multi-Output Device set as Live's output, ffmpeg, and a
one-time Microphone grant. If no loopback device is found the reply explains
how to install it and names the manual-export fallback. Returns the WAV path
(in the temp dir) — feed it to analyze_audio / compare_audio.Inputs: bars, solo, scene, device, +7 more. Returns: result
remove_notes_from_clipA
Remove MIDI notes from a clip within a time/pitch region. Defaults clear the whole clip (from_time=0, full length, all pitches). time_span=None means 'to the end of the clip'.
Inputs: clip_index (required), track_index (required), from_time, time_span, +2 more. Returns: result
save_setA
File ▸ Save (Cmd-S) — for a Set already saved to disk. Requires Accessibility.
Inputs: no named parameters. Returns: result
save_set_asA
File ▸ Save As to a specific path, e.g. '.../projects// Project/.als'. Drives the macOS save sheet via AppleScript (best-effort) and returns expected_path — verify the file exists afterwards. Requires Accessibility.
Inputs: als_path (required). Returns: result
set_arrangement_recordA
Arm/disarm Arrangement (global) Record — the transport's ● button. With it ON, launching Session clips/scenes records them into the Arrangement timeline. This is the capability that lets a Session-view loop be captured for export (Live's exporter only renders the Arrangement). For the full automated capture use capture_session_to_arrangement instead.
Inputs: on. Returns: result
set_clip_colorA
Set a clip's color as a packed RGB integer (0xRRGGBB).
Inputs: color (required), clip_index (required), track_index (required). Returns: result
set_clip_loopA
Set a clip's loop attributes (only the ones you pass are changed): looping on/off, loop_start/loop_end (beats), start_marker/end_marker.
Inputs: clip_index (required), track_index (required), looping, loop_end, +3 more. Returns: result
set_clip_nameB
Set the name of a clip.
Inputs: name (required), clip_index (required), track_index (required). Returns: result
set_clip_trigger_quantizationA
Set the global clip-launch quantization by index (0 = None, which launches clips immediately). capture_session_to_arrangement sets this to None for a tight start and restores it afterwards; exposed here for manual control.
Inputs: value. Returns: result
set_device_enabledA
Turn a device on or off (its bypass / 'Device On' switch). track='master'/'return:N' targets those tracks.
Inputs: on (required), track_index (required), device_index (required), track. Returns: result
set_device_parameterA
Set one device parameter — this is how you change a sound's tone.
- parameter: the parameter index (int) OR its exact name (str, case-insensitive).
- value: native units. For a continuous param a float in [min, max]
(e.g. a frequency/dB/ms). For a quantized param, either an integer index
into value_items or the exact value_items label string (e.g. "Lowpass").
- value_normalized: alternative to value, a 0.0-1.0 fraction mapped to
min + x*(max-min); for quantized params it picks the value_items index.
Provide exactly one of value / value_normalized. The reply reports the
resulting display_value and whether the write applied (a parameter driven
by a macro is not writable).Inputs: parameter (required), track_index (required), device_index (required), track, +2 more. Returns: result
set_macroA
Set a Rack macro by index (0-based) or name. Same value/value_normalized semantics as set_device_parameter.
Inputs: macro (required), track_index (required), device_index (required), value, +1 more. Returns: result
set_metronomeA
Turn the metronome on or off.
Inputs: on (required). Returns: result
set_scene_nameC
Set a scene's name.
Inputs: name (required), scene_index (required). Returns: result
set_song_positionA
Move the transport playhead to a position in beats from song start.
Inputs: beats (required). Returns: result
set_tempoB
Set the session tempo in BPM.
Inputs: tempo (required). Returns: result
set_time_signatureA
Set the song time signature, e.g. numerator=3, denominator=4 for 3/4.
Inputs: numerator (required), denominator (required). Returns: result
set_track_armA
Arm (on=True) or disarm (on=False) a track for recording.
Inputs: on (required), track_index (required). Returns: result
set_track_colorA
Set a track's color as a packed RGB integer (0xRRGGBB, e.g. 16711680 = red).
Inputs: color (required), track_index (required). Returns: result
set_track_muteA
Mute (on=True) or unmute (on=False) a track.
Inputs: on (required), track_index (required). Returns: result
set_track_nameC
Set the name of a track.
Inputs: name (required), track_index (required). Returns: result
set_track_panA
Set a track's pan, -1.0 (hard left) .. 0.0 (center) .. +1.0 (hard right). track='master'/'return:N' targets those tracks.
Inputs: value (required), track_index (required), track. Returns: result
set_track_sendC
Set a track's send level (0.0-1.0) to return track send_index (0-based).
Inputs: send_index (required), track_index (required), value, value_normalized. Returns: result
set_track_soloA
Solo (on=True) or unsolo (on=False) a track.
Inputs: on (required), track_index (required). Returns: result
set_track_volumeA
Set a track's volume fader (0.0-1.0). NOTE: this is the fader position, not dB — ~0.85 ≈ 0 dB (unity), 1.0 ≈ +6 dB. value and value_normalized are equivalent here (the fader range is already 0..1). Reply reports the dB. track='master' sets the master fader.
Inputs: track_index (required), track, value, value_normalized. Returns: result
start_playbackA
Start the session transport.
Inputs: no named parameters. Returns: result
stop_clipA
Stop a playing clip slot.
Inputs: clip_index (required), track_index (required). Returns: result
stop_playbackA
Stop the session transport.
Inputs: no named parameters. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 62 tools
Most tools target distinct resources and actions, but there is some intentional overlap between get_device_parameters/get_macros and set_device_parameter/set_macro, and record_and_analyze is a composite of record_audio and analyze_audio. These are documented clearly enough to avoid confusion in practice.
Tool names overwhelmingly follow a verb_noun snake_case pattern (e.g., create_midi_track, set_device_parameter, delete_scene). Minor exceptions like health, new_live_set, and save_set_as are still readable and do not disrupt the overall predictability.
At 62 tools, the server is far beyond the 25+ threshold that indicates an over-heavy toolset. While Ableton is a complex domain, the count feels overwhelming and many tools could be consolidated (e.g., record_and_analyze already merges two).
The toolset covers the full creative workflow: session/track/clip management, device control, scenes, transport, audio capture, analysis, and comparison. The main gap is that export is not fully automated—open_export_dialog requires manual confirmation—but the capture-to-arrangement path fills most of the pipeline.
Related MCP Connectors
MCP server for Producer/Riffusion AI music generation
Remote MCP server for audio stem separation, denoise, reverb, and MIDI export.
Create, co-edit, analyze, publish, and export collaborative step-sequencer sessions through MCP.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for Ableton Live that exposes the Live Object Model to LLMs, enabling natural language control of music production.3684 npm11MIT
- AlicenseAqualityDmaintenanceMCP server that bridges Ableton Live with AI models, enabling real-time project inspection and control such as track overview, device parameters, and audio analysis.1236 PyPI1MIT
- FlicenseBqualityDmaintenanceMCP server for controlling Ableton Live, enabling AI assistants to interact with Live sessions through tools for track/clip/scene management, playback control, and device parameter adjustments.48-
- AlicenseNot gradedqualityCmaintenanceAn MCP server that exposes Ableton Live control (session state, transport, tracks, devices, clips, MIDI note editing) as tools for LLM agents, enabling natural language manipulation of a Live session.1MIT