Harmony, MIDI generation, and converted-MIDI cleanup
Better Ableton MCP can analyze the MIDI already in a Live Set, create new melody or chord clips that fit it, derive a chord progression from a selected monophonic audio phrase, and clean common artifacts from Ableton's Convert Melody/Harmony to MIDI results. The "AI" label on generated clips is a naming convention. Optional THIRI requests can enrich locally detected chords, reharmonize chord symbols, or replace local triads with hosted voicings; the core workflows remain available offline.
Track and clip indices are zero-based. Use the session-inspection tools first if you do not know the indices in the current Set.
Choosing source material
analyze_track_harmony, analyze_midi_progression, and
generate_for_tracks read MIDI notes from the tracks supplied in
track_indices or source_track_indices. Audio clips are ignored by those
tools; use generate_chords_for_selected_audio for a warped, monophonic
Arrangement phrase without first converting it to MIDI.
Ableton's audio-to-MIDI conversion is only needed when you specifically want a
note transcription for the MIDI cleanup workflow. Muted MIDI notes are ignored
for MIDI key inference.
clip_scope controls where the server looks:
| Value | Material included |
|---|---|
session |
MIDI clips in Session View |
arrangement |
MIDI clips in Arrangement View |
both |
Both views (the default) |
Arrangement-only source material is supported: analyze_track_harmony and
generate_for_tracks do not require any Session clips when clip_scope is
arrangement (or when both finds notes only in Arrangement View). The Remote
Script normalizes Live's MIDI-note values before sending them to the server, so
the object-based note API used by current Live 11 and Live 12 releases and the
older tuple/dictionary representations have the same behavior.
Selecting a Group Track automatically expands the selection to all nested descendant tracks. An empty source-track list is interpreted by the Remote Script as all tracks, although passing an explicit list is safer and makes the result easier to reproduce.
The Remote Script reads at most 4,096 notes for key analysis and accompaniment
generation. analyze_midi_progression requests up to 20,000 notes and fails
instead of returning a partial progression when that limit is reached.
Analyze harmony
analyze_track_harmony
Infers one major or natural-minor key from selected MIDI material and returns a duration-weighted pitch-class profile.
| Parameter | Type | Default | Description |
|---|---|---|---|
track_indices |
list of integers | required | Source tracks; a Group Track includes its descendants. |
clip_scope |
string | both |
session, arrangement, or both. |
Example request:
Analyze the harmony in tracks 2, 3, and 6, using both Session and Arrangement clips.
Equivalent arguments:
A response has this shape:
{
"analysis": {
"root": 0,
"mode": "major",
"name": "C major",
"confidence": 1.0,
"pitch_classes": {
"C": 4.0,
"E": 2.0,
"G": 3.0
}
},
"source_note_count": 3
}
The analyzer weights each pitch class by note duration (with a minimum weight
of 0.125 beats), then scores all 24 major/minor candidates by in-scale coverage
plus smaller tonic and dominant bonuses. confidence is the fraction of the
weighted material inside the winning scale. It is coverage, not a statistical
probability, and relative modes or harmonically ambiguous loops can produce a
plausible but musically debatable answer. Only major and natural minor are
considered; modes, harmonic minor, melodic minor, chromatic key changes, and
chord labels are not detected.
With no notes, the underlying analyzer's neutral fallback is C minor with
confidence: 0.0. Generation rejects an empty source instead of using that
fallback.
analyze_midi_progression
Detects one chord candidate in each non-empty bar of the selected MIDI clips. Pitch-class evidence and key inference are computed locally.
| Parameter | Type | Default | Description |
|---|---|---|---|
track_indices |
list of integers | required | MIDI sources; a Group Track includes its descendants. |
clip_scope |
string | both |
session, arrangement, or both. |
beats_per_bar |
number | 4.0 |
Analysis window from 0.25 through 32 beats. |
theory_provider |
string | auto |
auto, local, or thiri. |
{
"track_indices": [2, 5],
"clip_scope": "arrangement",
"beats_per_bar": 4.0,
"theory_provider": "auto"
}
The local detector compares duration-weighted pitch classes against major,
minor, diminished, augmented, suspended, seventh, major-seventh,
minor-seventh, half-diminished, and diminished-seventh templates. Muted notes
and empty bars are ignored. The response includes source track/view/clip
metadata, bar timing, MIDI pitches, detected symbol/root/quality, template
pitch classes, confidence, inferred key, and analysis_provider.
With THIRI enabled, only each locally detected chord symbol and inferred key
are sent to /v2/analyze; raw MIDI, audio, track names, and clip names stay
local. Repeated chord symbols within one call reuse the first response. Returned
theory data is attached to each chord. If quota headers are present,
thiri_quota contains limit and/or used.
Provider behavior
localnever makes a THIRI request.autouses THIRI whenTHIRI_API_KEYis configured. Without a key it stays local. On a hosted error it returns the local result withanalysis_provider="local"and aprovider_warning.thirirequires a key and fails on configuration, service, or quota errors instead of silently falling back.
All local detection remains available offline.
reharmonize_chord_progression
Sends chord symbols to THIRI and returns deterministic alternatives. It always
requires THIRI_API_KEY, has no local fallback, and does not read or modify
Ableton Live.
| Parameter | Type | Default | Description |
|---|---|---|---|
progression |
list of strings | required | Between 1 and 32 non-blank chord symbols. |
technique |
string | auto |
auto, tritone_sub, ii_v_insertion, modal_interchange, diminished_passing, secondary_dominant, chain_of_dominants, coltrane_changes, or backdoor. |
key |
string | empty | Optional compact key context such as C or F#m. |
The response contains analysis_provider="thiri" plus THIRI's response fields.
When available, thiri_quota contains limit and/or used.
Generate a matching clip
generate_for_tracks
Analyzes source tracks and creates either a melody or one-bar-per-chord progression in a Session clip.
| Parameter | Type | Default | Description |
|---|---|---|---|
source_track_indices |
list of integers | required | MIDI sources used for key and pitch-class weighting. |
kind |
string | melody |
melody or chords. |
bars |
integer | 4 |
Length from 1 through 64 bars. Each bar is currently fixed at four beats. |
target_track_index |
integer | -1 |
Existing MIDI track, or -1 to append and name a new MIDI track. |
target_clip_index |
integer | -1 |
Empty Session slot, or -1 for the first empty slot. |
clip_scope |
string | both |
Source scope: session, arrangement, or both. |
density |
number | 0.55 |
Melody event probability from 0.05 through 1.0; ignored for chords. |
seed |
integer | 0 |
Melody random seed; ignored for chords. |
Example requests:
Create an 8-bar melody for tracks 2 and 3 on a new track. Use density 0.65 and seed 17.
{
"source_track_indices": [2, 3],
"kind": "melody",
"bars": 8,
"target_track_index": -1,
"target_clip_index": -1,
"clip_scope": "both",
"density": 0.65,
"seed": 17
}
Put four bars of matching chords in empty Session slot 5 on MIDI track 8.
{
"source_track_indices": [2, 3],
"kind": "chords",
"bars": 4,
"target_track_index": 8,
"target_clip_index": 5
}
The response identifies the created track and slot, inferred key, note count,
clip name, and seed. New tracks and all generated clips are named
AI <key> Melody or AI <key> Chords; the target track is colored with the
organizer's music color. An existing target track is not renamed. No
instrument is loaded, so a new track may need an instrument before it makes
sound.
Generation always creates a Session View clip of bars * 4 beats. The
target must be a MIDI track and the Session slot must be empty. -1 chooses the
first empty slot, not a new scene; the operation fails if the track has no empty
slots. Arrangement clips may inform the harmony but cannot be the generation
target.
Melody behavior and repeatability
Melodies use half-beat candidate positions and pitches from MIDI 60 through 84 (C4 through C6 in the common convention), constrained to the inferred scale. Source pitch classes with longer total duration receive more weight, while a continuity bias favors pitches near the previous generated note. Integer beats are more likely than offbeats and use velocity 92 rather than 78. Durations are 0.5 or 1 beat.
The same source material, arguments, and seed produce the same note list with
the same implementation. Change seed for another repeatable variant.
density is probabilistic rather than an exact notes-per-bar control, and the
chance is capped at 95 percent. One-beat notes can overlap a note generated at
the next half-beat, so the result is not guaranteed to be strictly monophonic.
Chord behavior and repeatability
Chord generation is fully deterministic and does not use seed or density.
It writes one diatonic triad per four-beat bar at velocity 76 in a compact lower
register. Major uses a repeating I–V–vi–IV pattern; minor uses i–VI–iv–v. A
four-bar request therefore creates 12 notes, and longer requests repeat the
progression.
Generation is algorithmic and intentionally small in scope. It does not inspect rhythm, tempo, meter, chord changes, clip boundaries, groove, or Arrangement position when composing. Audition and edit the result as a starting point.
Generate chords for a selected vocal or monophonic audio phrase
generate_chords_for_selected_audio
This high-level tool reads the selected Arrangement audio clip, detects pitches directly from its local source audio, reduces confident frames to beat-aligned pitch-class evidence, chooses a diatonic triad for each meter-aware bar, and creates a populated MIDI clip. It does not ask Live to convert the audio to MIDI and does not create an intermediate MIDI transcription. The generated accompaniment itself is MIDI so it can be voiced with any Live instrument.
The defaults analyze the entire selected Detail View clip, follow its exact duration, create a new MIDI track, and align the new Arrangement clip to the audio clip's start. In an incomplete final bar, the last chord is shortened to the selected audio's end.
Install the optional local analysis dependencies first:
The extra installs librosa and soundfile. The source format must be readable
by that local decoder stack. WAV, FLAC, and OGG are dependable choices on
typical installations; codec support can vary, so convert to WAV if another
format cannot be read.
Select the source audio
For the default selection_mode="clip" workflow:
- In Arrangement View, click the warped vocal or other monophonic audio clip. The track must be Live's selected track and that same clip must be shown in Detail/Clip View.
- Ask naturally:
Make a chord progression that goes with the selected vocal clip.
No Arrangement Loop is needed for the default whole-clip workflow. To analyze
only part of the clip, drag across that phrase, press Cmd-L on macOS or
Ctrl-L on Windows, confirm that Live's Arrangement Loop is enabled, and set
selection_mode="loop". Only the loop/clip intersection is analyzed.
Live does not expose an arbitrary Arrangement time selection through this integration. Selecting time alone is therefore insufficient for a partial phrase; the enabled Arrangement Loop supplies the precise range.
With bars=0, bar count is inferred from the selected range and the output ends
at exactly that range's end. With an explicit bars value, output uses that
many complete bars in the Live Set's current meter: vocal evidence after the
output window does not affect chord choices, while output bars beyond a shorter
source range are filled from the inferred key and progression scoring.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
bars |
integer | 0 |
0 automatically follows the selected audio's exact duration; 1 through 64 creates that many complete bars. Bar length follows the Live Set's current time signature. |
selection_mode |
string | clip |
clip analyzes the whole selected Detail View Arrangement clip; loop analyzes its intersection with the enabled Arrangement Loop. |
target_track_index |
integer | -1 |
Existing MIDI track, or -1 to append and name a new MIDI track. |
target_view |
string | arrangement |
arrangement creates at the analyzed range's start; session uses the first empty Session slot. |
seed |
integer | 0 |
Deterministic tie-breaker between equally scored progressions. |
minimum_pitch_confidence |
number | 0.65 |
pYIN confidence threshold from 0.05 through 1.0; lower values admit less certain frames. |
theory_provider |
string | auto |
auto, local, or thiri. Controls MIDI voicing only; audio analysis and chord selection remain local. |
voicing_style |
string | triad |
THIRI voicing style; ignored when the resolved provider is local. |
Example with explicit arguments:
{
"bars": 0,
"selection_mode": "clip",
"target_track_index": -1,
"target_view": "arrangement",
"seed": 12,
"minimum_pitch_confidence": 0.65,
"theory_provider": "auto",
"voicing_style": "triad"
}
The response is JSON containing the analyzed track, clip, source range, inferred
major or natural-minor key and confidence, detected pitch-frame count, mean
pitch confidence, resolved bar count, exact output length in beats, chosen
triad names, zero-based scale degrees, seed, and created destination. It also
reports analysis_mode="direct_audio_pitch_class", the resolved
theory_provider, and applied voicing_style. Chord entries use compact
lead-sheet names such as C, Am, and Bdim.
Optional THIRI voicings
Local pitch detection, key inference, and chord choice always happen first.
local creates compact local_triad voicings without a hosted request. auto
uses THIRI when a key is configured; if THIRI fails or returns unusable MIDI,
the clip is still created with local triads and a provider_warning. Explicit
thiri requires every hosted voicing to succeed; on failure no MIDI clip is
created.
Supported voicing_style values are rootless, bill_evans, shell, triad,
pad, guide-tones, guide-tone-1, guide-tone-2,
both-guide-tones, drop-2, and drop-3. THIRI receives only the chord
symbol, style, octave 3, inferred key, and previous returned note names for
voice leading. It never receives audio samples or source names.
THIRI responses add voice_leading_scores; individual values may be null. When
available, thiri_quota contains limit and/or used. Local responses report
voicing_style="local_triad".
Audio-analysis and harmony behavior
- The feature is intended for a single foreground pitch: lead vocal, whistle, monophonic instrument, or similarly clear material. Polyphonic vocals, backing tracks, dense effects, and noisy recordings can produce misleading pitch estimates.
- Warp must be enabled, Re-Pitch mode is rejected, and the clip must have at least two warp markers. The tool maps Arrangement beats through those markers to read only the selected source-file range. It applies the clip's coarse and fine transposition before harmony analysis.
- Pitch detection downmixes the selected source range to mono at 22.05 kHz and
uses pYIN from A1 through C7. Frames below
minimum_pitch_confidenceand unvoiced frames are discarded. Each accepted frequency is rounded directly to an octave-independent pitch class; no MIDI-note event representation is created. The tool fails rather than creating chords when no reliable frames remain. - The inferred key uses the same 24-candidate major/natural-minor analyzer as
MIDI generation. For each bar, chord scoring favors sustained vocal notes and
then considers functional transitions and smooth triad voice leading. Chords
use MIDI pitches 48 through 67 (shown as C2 through G3 in Ableton) at velocity
76, one triad per bar. The last triad is trimmed when
bars=0ends within a bar. - A request is rejected if its warp-mapped source range exceeds 300 seconds.
- The result is an algorithmic starting point, not semantic lyric analysis, source separation, polyphonic transcription, or chord recognition.
Destination, Undo, and rollback
With the defaults, the new track and clip are named
AI <key> Vocal Chords, use the organizer's music color, and start at the
selected clip's Arrangement beat. Their length matches the clip rather than a
fixed bar count. No instrument is loaded. In Session View, the tool creates the
clip in the first empty slot and does not preserve the Arrangement start
position.
For an existing target, the Remote Script requires an unfrozen MIDI track. It refuses an Arrangement range that overlaps an existing clip and refuses a Session target with no empty slot. It validates note and destination data before mutation, groups creation into one Ableton Undo step when Live exposes undo grouping, and attempts to delete a partial generated clip or newly created track if creation fails. Rollback never deletes an existing user-owned target track. As with any best-effort rollback against a host application, check Live if it reports that rollback itself failed.
The project supports Live 11 and 12. When the installed Live API supports direct Arrangement MIDI-clip creation, the Remote Script uses it. Otherwise it creates a temporary Session clip, duplicates it to Arrangement, and deletes the temporary clip; that fallback requires an empty Session slot.
Local file and privacy requirements
Pitch analysis happens in the Python MCP server process and audio samples are
not uploaded to THIRI. The source path reported by Live
must be an absolute, readable file path on the MCP server's machine. This works
naturally when Live and the MCP server run on the same computer. If
ABLETON_HOST points to a different computer, both machines must expose the
source file at the path Live reports.
Clean Ableton audio-to-MIDI conversions
The cleaner targets common artifacts from Ableton's Convert Melody to MIDI and Convert Harmony to MIDI commands. It operates on every MIDI clip on one track within the selected scope. Preview first for valuable material.
preview_converted_midi_cleanup
Runs the complete analysis without changing Live.
| Parameter | Type | Default | Description |
|---|---|---|---|
track_index |
integer | required | Track whose converted MIDI clips should be inspected. |
mode |
string | auto |
auto, melody, or harmony. |
strength |
number | 0.55 |
Cleanup strength from 0.0 through 1.0. |
clip_scope |
string | both |
session, arrangement, or both. |
Example:
Preview cleanup of the converted melody on track 7 at strength 0.5, but only in Session View.
The JSON report includes totals and a per-clip address (track_index, view,
and clip_index), detected mode, before/after counts, merged-fragment count,
duration thresholds, and removal-reason counts. removed_preview contains at
most the first 20 proposed removals per clip. Merge details are summarized as a
count rather than listed in the public report.
clean_converted_midi
Accepts the same parameters, runs the same analysis, then replaces the notes in
all matching clips. Its response adds status: "cleaned" and an applied
summary listing each changed clip and final note count.
Example:
Clean converted harmony on track 4 at strength 0.4, preserving chords in both views.
The Remote Script groups replacement of all selected clips into one Ableton Undo step when the installed Live API provides undo grouping. Undo immediately if the musical result is not what you intended.
Modes
melodytreats each onset as monophonic. When notes begin within 0.045 beats of one another, it retains the candidate favored by duration, velocity, and continuity with the previous pitch, and reports the others assimultaneous_melody_artifact.harmonypreserves simultaneous chord tones and skips that monophonic pass.autochooses independently for each clip. It selects harmony when at least 25 percent of onset clusters contain multiple notes, or at least 10 percent contain three or more notes; otherwise it selects melody.
Force harmony for arpeggios with intentional overlaps or sparse chords that
auto-detection might call melodic. Force melody only when simultaneous notes
really are conversion ghosts.
What the cleaner changes
Before scoring, notes are normalized to MIDI pitch 0–127, velocity 1–127, and a minimum duration of 0.001 beats. The cleaner derives its thresholds from each clip's median duration, velocity, pitch, and pitch spread. It removes a note conservatively when multiple signals agree, using these report reason codes:
| Reason | Meaning |
|---|---|
short_artifact |
An unusually short note also looks weak, isolated, rare, or out of range. |
range_outlier |
A register outlier is also short or weak. |
weak_rare_pitch |
A weak, short note has little pitch-class support in the clip. |
isolated_blip |
A unique short note has no nearby pitch neighbor. |
simultaneous_melody_artifact |
Melody mode discarded an extra note at the same onset. |
Higher strength raises short/weak/rare thresholds, narrows the accepted pitch
range, gives pitch continuity more influence in melody mode, and permits wider
same-pitch fragment gaps to merge. Start at the default 0.55; lower it when
the conversion contains intentional grace notes, wide leaps, quiet notes, or
chromatic color.
After removal, overlapping notes of the same pitch are always merged. A tiny same-pitch fragment (one side no longer than 0.35 beats) is also merged across a gap of 0.015 beats at strength 0, increasing to 0.07 beats at strength 1. The merged note spans the full combined interval and keeps the higher velocity. This can combine intentional repeated or layered same-pitch voices.
Muted notes bypass the initial artifact-removal tests, but in melody mode they still participate in simultaneous-onset selection. Cleanup preserves only pitch, start time, duration, velocity, and mute state. Because it rewrites the whole clip, per-note expression available in newer Live versions—such as note probability, velocity deviation, release velocity, and MPE data—is not retained.
Cleanup reads at most 20,000 notes across the selected track and scope. Do not apply it to a selection near or above that size: the current public report does not expose the Remote Script's truncation flag, and rewriting a partially read clip could discard notes beyond the limit. Split or narrow the scope first.
Practical workflow
- Run
analyze_track_harmonyto verify that the selected sources imply the key you expect. - Run
analyze_midi_progressionwhen you need bar-level chord labels. Usereharmonize_chord_progressiononly when you want hosted alternatives. - Call
generate_for_trackswith an explicit source list and seed. Audition the generated Session clip and edit it as needed. - To harmonize a vocal directly, select the warped Arrangement clip, loop the
intended phrase with Cmd-L/Ctrl-L, and call
generate_chords_for_selected_audio. Verify the inferred key and audition the result with an instrument on the generated MIDI track. - For audio-to-MIDI results, call
preview_converted_midi_cleanupwith the correct mode and a conservative strength. - Review every clip's before/after count and reason summary, then call
clean_converted_midiwith the same arguments. Use Ableton Undo if needed.
Implementation references
- MCP tool validation and Live operations:
src/better_ableton_mcp/server.py - Key inference and deterministic generation:
src/better_ableton_mcp/harmony.py - Optional THIRI REST client:
src/better_ableton_mcp/thiri.py - Local pitch detection and Warp-marker mapping:
src/better_ableton_mcp/audio_analysis.py - Converted-MIDI detection and cleanup:
src/better_ableton_mcp/midi_cleanup.py - Live clip reading and replacement:
BetterAbletonMCP_Remote_Script/__init__.py - Behavior covered by tests:
tests/test_harmony.pytests/test_audio_analysis.py,tests/test_server_audio.py,tests/test_thiri.py,tests/test_server_thiri.py,tests/test_remote_script.py, andtests/test_midi_cleanup.py