livepilot 1.16.1 → 1.17.1

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +311 -0
  2. package/README.md +16 -15
  3. package/installer/codex.js +14 -0
  4. package/m4l_device/LivePilot_Analyzer.amxd +0 -0
  5. package/m4l_device/livepilot_bridge.js +1 -1
  6. package/mcp_server/__init__.py +1 -1
  7. package/mcp_server/atlas/__init__.py +85 -0
  8. package/mcp_server/atlas/device_atlas.json +3183 -382
  9. package/mcp_server/atlas/device_techniques_index.json +1510 -0
  10. package/mcp_server/atlas/enrichments/__init__.py +1 -0
  11. package/mcp_server/atlas/enrichments/audio_effects/amp.yaml +112 -0
  12. package/mcp_server/atlas/enrichments/audio_effects/audio_effect_rack.yaml +77 -0
  13. package/mcp_server/atlas/enrichments/audio_effects/cabinet.yaml +81 -0
  14. package/mcp_server/atlas/enrichments/audio_effects/corpus.yaml +128 -0
  15. package/mcp_server/atlas/enrichments/audio_effects/envelope_follower.yaml +99 -0
  16. package/mcp_server/atlas/enrichments/audio_effects/external_audio_effect.yaml +64 -0
  17. package/mcp_server/atlas/enrichments/audio_effects/looper.yaml +85 -0
  18. package/mcp_server/atlas/enrichments/audio_effects/resonators.yaml +121 -0
  19. package/mcp_server/atlas/enrichments/audio_effects/snipper.yaml +17 -0
  20. package/mcp_server/atlas/enrichments/audio_effects/spectrum.yaml +61 -0
  21. package/mcp_server/atlas/enrichments/audio_effects/tuner.yaml +43 -0
  22. package/mcp_server/atlas/enrichments/audio_effects/utility.yaml +118 -0
  23. package/mcp_server/atlas/enrichments/audio_effects/vocoder.yaml +94 -0
  24. package/mcp_server/atlas/enrichments/instruments/analog.yaml +11 -0
  25. package/mcp_server/atlas/enrichments/instruments/bass.yaml +11 -0
  26. package/mcp_server/atlas/enrichments/instruments/bell_tower.yaml +38 -0
  27. package/mcp_server/atlas/enrichments/instruments/collision.yaml +11 -0
  28. package/mcp_server/atlas/enrichments/instruments/drift.yaml +11 -0
  29. package/mcp_server/atlas/enrichments/instruments/drum_rack.yaml +142 -0
  30. package/mcp_server/atlas/enrichments/instruments/electric.yaml +11 -0
  31. package/mcp_server/atlas/enrichments/instruments/emit.yaml +11 -0
  32. package/mcp_server/atlas/enrichments/instruments/meld.yaml +11 -0
  33. package/mcp_server/atlas/enrichments/instruments/operator.yaml +11 -0
  34. package/mcp_server/atlas/enrichments/instruments/poli.yaml +11 -0
  35. package/mcp_server/atlas/enrichments/instruments/sampler.yaml +12 -0
  36. package/mcp_server/atlas/enrichments/instruments/simpler.yaml +15 -0
  37. package/mcp_server/atlas/enrichments/instruments/tension.yaml +11 -0
  38. package/mcp_server/atlas/enrichments/instruments/vector_fm.yaml +11 -0
  39. package/mcp_server/atlas/enrichments/instruments/vector_grain.yaml +11 -0
  40. package/mcp_server/atlas/enrichments/instruments/wavetable.yaml +11 -0
  41. package/mcp_server/atlas/enrichments/midi_effects/filler.yaml +17 -0
  42. package/mcp_server/atlas/enrichments/utility/performer.yaml +15 -0
  43. package/mcp_server/atlas/enrichments/utility/vector_map.yaml +21 -0
  44. package/mcp_server/atlas/tools.py +291 -0
  45. package/mcp_server/m4l_bridge.py +19 -2
  46. package/mcp_server/sample_engine/tools.py +201 -128
  47. package/mcp_server/splice_client/http_bridge.py +319 -116
  48. package/mcp_server/tools/automation.py +168 -0
  49. package/package.json +2 -2
  50. package/remote_script/LivePilot/__init__.py +1 -1
  51. package/remote_script/LivePilot/arrangement.py +216 -1
  52. package/server.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,316 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.17.1 — Splice auto-reconnect + Codex installer fix (April 23 2026)
4
+
5
+ Two bug fixes discovered in a parallel worktree hours after v1.17.0
6
+ shipped. Non-breaking, test-locked, ships as a patch.
7
+
8
+ ### Fixed
9
+
10
+ - **Splice client auto-reconnect** (`mcp_server/sample_engine/tools.py`):
11
+ Every Splice MCP tool now reconnects the shared gRPC client on demand
12
+ via a new `_ensure_splice_client_connected()` helper. Before this fix,
13
+ if the Splice desktop app launched AFTER the MCP server (common when
14
+ users start the MCP via Claude Code before booting Splice), every
15
+ Splice tool stayed stuck in a disconnected state until the WHOLE MCP
16
+ server was restarted. The fix re-checks on every tool invocation, so
17
+ the first successful Splice-desktop boot auto-recovers the client
18
+ transparently. Tools affected: `get_splice_credits`,
19
+ `splice_catalog_hunt`, `search_samples` (when routing through Splice),
20
+ plus every other Splice tool that reads from the shared context.
21
+ 3 new regression tests in `tests/test_splice_reconnect_tools.py` lock
22
+ the reconnect behavior.
23
+ - **Codex plugin installer writes `.mcp.json`** (`installer/codex.js`):
24
+ The installer was copying plugin files into the Codex plugins
25
+ directory but omitting the `.mcp.json` config that tells Codex how
26
+ to launch the MCP server. Codex users had to manually create the
27
+ file or run the command with additional flags. Now
28
+ `writeLocalMcpConfig(destDir)` writes the correct
29
+ `{mcpServers: {livepilot: {command, args}}}` shape during install.
30
+ 1 new regression test in `tests/test_codex_plugin_installer.py`
31
+ asserts the file content.
32
+
33
+ ### Verified
34
+
35
+ 155/155 tests green. `sync_metadata.py --check`: all metadata in sync
36
+ at version=1.17.1, tools=426, domains=52, bridge_cmds=30, enriched=120.
37
+
38
+ ### Distribution
39
+
40
+ Same channels as v1.17.0 — GitHub release + npm + `.mcpb` + plugin
41
+ cache. Tool count and domain count unchanged; this is purely a
42
+ reliability patch.
43
+
44
+
45
+ ## 1.17.0 — 2026-04-22 handoff close-out (April 22 2026, late)
46
+
47
+ Closes every item in the 2026-04-22 handoff document: Splice's
48
+ Describe-a-Sound + Variations go LIVE via captured GraphQL
49
+ endpoints, the M4L Analyzer gains a 9th spectrum band (sub_low
50
+ 20-60 Hz), track-level arrangement automation lands via a
51
+ two-phase session-record workaround, the atlas gains a
52
+ by_pack index + `atlas_pack_info` MCP tool, the device atlas
53
+ adds 13 enrichments including a Drum Rack container entry, and
54
+ Tier C of the pack-knowledge reference expands from 7 clusters
55
+ to 14 individually-documented packs.
56
+
57
+ **Tool count**: 422 → 426 (+5 new, −1 retired):
58
+ - `+` `atlas_pack_info` — inspect a pack's device list + enrichment coverage
59
+ - `+` `atlas_describe_chain` — free-text describe-a-chain, mirror of
60
+ `splice_describe_sound` for the device library. "A granular pad like
61
+ Tim Hecker" → device chain proposal via artist + genre vocabulary
62
+ matching
63
+ - `+` `atlas_techniques_for_device` — reverse-lookup: what techniques
64
+ reference this device? Reads an auto-generated index of 146 technique
65
+ cross-references across 58 devices
66
+ - `+` `set_arrangement_automation_via_session_record` — T5 workaround,
67
+ two-phase protocol with tempo-scaled sleep
68
+ - `+` `splice_http_diagnose` — per-endpoint verified-status reporter
69
+ - `−` `splice_search_with_sound` — retired (user handles
70
+ audio-reference search directly in Splice's UI; capture recipe
71
+ preserved at `docs/2026-04-22-splice-https-capture-recipe.md`)
72
+
73
+ **Domain count**: unchanged at 52.
74
+ **Enrichment YAMLs**: 107 → 120 (+13).
75
+ **Atlas pack coverage**: 0 → 641 devices indexed (614 Core Library
76
+ via auto-heuristic + 27 explicit-pack YAML declarations).
77
+ **Signature-technique coverage**: 32 → 47 enrichment files have the
78
+ `signature_techniques` field (+15 files × 3 techniques each = +45
79
+ technique entries from native-synth backfill). Coverage rose from
80
+ 27% → 39% of enrichments.
81
+ **Tests**: 2644 → 2696+ (+52 new regression guards).
82
+
83
+ ### Live-verified end-to-end
84
+
85
+ Against a running Ableton 12.4 + Splice desktop 5.4.9 session on
86
+ 2026-04-22:
87
+
88
+ - `get_master_spectrum()` → 9 keys with `sub_low` first, real-audio
89
+ energy distribution (`sub_low=0.0003 sub=0.0008 low=0.0064 …`)
90
+ - `atlas_pack_info("Drone Lab")` → Harmonic Drone Generator in
91
+ both Sounds and M4L variants with URIs
92
+ - `splice_describe_sound("warm dub techno chord stab", limit=5)` →
93
+ 5 real samples out of 4100 total hits (Dub Techno 2 pluck, NEONIC
94
+ atmos, Visions chord, Organic Elements 2, Underground Techno),
95
+ with Splice's ML rephrasing `rephrased_query_string: "dub techno,
96
+ chords, stabs, warm"`
97
+
98
+ ### Splice HTTPS bridge — endpoint capture
99
+
100
+ Captured via mitmproxy against Splice desktop v5.4.9 (unpinned TLS,
101
+ intercepts cleanly once CA is trusted). Two GraphQL operations
102
+ wired:
103
+
104
+ - **`SamplesSearch`** at `surfaces-graphql.splice.com/graphql` —
105
+ describe + keyword search in one operation, flagged via
106
+ `semantic=1` + `rephrase=true`. 5938-char query embedded as
107
+ `mcp_server/splice_client/graphql_queries/samples_search.graphql`
108
+ - **`AssetSimilarSoundsQuery`** at the same endpoint — Splice's
109
+ "Variations" / "Similar Sounds" feature. Input is a sample
110
+ `uuid` + `isLegacy` bool; returns up to 10 recommendations.
111
+ 886-char query embedded as
112
+ `mcp_server/splice_client/graphql_queries/asset_similar_sounds.graphql`
113
+ - Auth: `Authorization: Bearer <JWT>` via local gRPC `GetSession`
114
+ RPC — no stored credentials, token rotates with the running
115
+ Splice desktop app
116
+ - User-Agent: LivePilot default (override via env var if
117
+ Cloudflare blocks — mimic pattern: `Splice Baelish/darwin/
118
+ arm64/arm64 5.4.9/<hash>/stable`)
119
+ - Response normalizer `_flatten_sample_item()` is shared between
120
+ both operations so samples from describe + variations flatten
121
+ to identical dicts — 14 new unit tests lock this invariant
122
+ - Per-endpoint `describe_verified` / `variation_verified` flags
123
+ replace the coarse `is_user_configured` gate
124
+
125
+ ### Changed
126
+
127
+ - `splice_generate_variation` signature changed: `(file_hash,
128
+ target_key, target_bpm, count)` → `(uuid, is_legacy)`. The
129
+ operation is a recommender lookup, not AI audio synthesis, so
130
+ target-key / target-bpm / count aren't API-supported. The
131
+ underlying GraphQL returns up to 10 similar samples with the
132
+ same flat shape as `splice_describe_sound` results.
133
+ - `splice_describe_sound` — status flipped from "scaffolded" to
134
+ "LIVE". Adds new `rephrase: bool = True` parameter surfacing
135
+ Splice's `rephrased_query_string` in the response.
136
+
137
+ ### Added
138
+
139
+ **Sub_low spectrum band** (T3 from handoff):
140
+ - M4L Analyzer `fffb~` filter bank: 8 bands → 9 bands. New band
141
+ center frequencies: `35 85 175 350 700 1400 2800 5600 12000`
142
+ (Hz), with `sub_low` (20-60 Hz) prepended to separate kick
143
+ fundamental from DC rumble
144
+ - `mcp_server/m4l_bridge.py`: `BAND_NAMES_8` + `BAND_NAMES_9`
145
+ auto-selected based on payload length — older frozen .amxd
146
+ builds (pre-v1.17) still work without re-freeze
147
+ - `LivePilot_Analyzer.amxd` re-frozen from modified
148
+ `LivePilot_Analyzer.maxpat` source, 6751650 bytes, synced to
149
+ repo / Max 9 Library cache / Ableton User Library
150
+ - `docs/2026-04-22-sub-low-band-max-workflow.md` — runbook for
151
+ future band-count changes (Max editor walkthrough)
152
+
153
+ **Track-level arrangement automation workaround** (T5 from handoff):
154
+ - New MCP tool `set_arrangement_automation_via_session_record` —
155
+ async two-phase protocol that creates a session clip with the
156
+ automation, arms the track, records into arrangement at a
157
+ target beat, cleans up
158
+ - Two new remote-script handlers:
159
+ `arrangement_automation_via_session_record_start` returns the
160
+ live `song.tempo` so the MCP layer can compute the sleep
161
+ duration, `_complete` stops record + locates the new
162
+ arrangement clip
163
+ - MCP layer sleeps `duration_beats × 60/tempo + 0.5s` with a
164
+ 600s ceiling and graceful exception handling — incomplete
165
+ sleep still tries to complete so tracks don't stay armed
166
+ - 17 new contract tests (two-phase ordering, tempo scaling,
167
+ ceiling, default-tempo fallback, start-failure short-circuit)
168
+
169
+ **Atlas `by_pack` index + `atlas_pack_info` tool** (T4):
170
+ - New `_by_pack` index on `AtlasManager`, populated from
171
+ enrichment YAML `pack:` fields plus a Core Library
172
+ auto-heuristic for native instruments/effects without an
173
+ explicit pack declaration
174
+ - New `pack_info(name)` and `list_packs()` methods
175
+ - New MCP tool `atlas_pack_info(pack_name)` — `""` returns the
176
+ full pack list with device counts, otherwise returns
177
+ `{pack, device_count, enriched_count, devices[...]}` for one
178
+ pack. Case-insensitive name lookup
179
+ - `genre_affinity` (enriched field) now feeds the `_by_genre`
180
+ index alongside the raw `genres` field, so
181
+ `microhouse`/`deep_minimal`/`dub_techno` tags added to YAMLs
182
+ post-v1.11 finally surface in genre lookups
183
+
184
+ **Drum Rack atlas enrichment + 12 audio-effects YAMLs** (T1/T2):
185
+ - New `instruments/drum_rack.yaml` — treats Drum Rack as a
186
+ meta-type container with per-pad key_parameters, 3 starter
187
+ recipes, 8 gotchas (including MIDI pitch conventions, chain
188
+ volume vs pad volume)
189
+ - 12 new audio-effects enrichments: `utility`, `corpus`,
190
+ `vocoder`, `tuner`, `spectrum`, `amp`, `cabinet`, `resonators`,
191
+ `looper`, `envelope_follower`, `audio_effect_rack`,
192
+ `external_audio_effect`. Takes `audio_effects/` count from 40
193
+ → 52
194
+ - Simpler + Sampler enrichments gain 3 new gotchas (Snap=OFF
195
+ silence bug, -12 dB default, slice base pitch = 36+N)
196
+ - `pack` field added to `_ENRICHMENT_FIELDS` allowlist — was
197
+ silently dropped from atlas JSON before; now drives the
198
+ `by_pack` index
199
+
200
+ **Pack-knowledge reference** (T7):
201
+ - `livepilot/skills/livepilot-core/references/pack-knowledge.md`
202
+ Tier C expanded from 7 merged clusters (~62 lines) to 14
203
+ individually-documented packs (Build and Drop, Drive and Glow,
204
+ Punch and Tilt, Skitter and Step, Trap Drums, Beat Tools, Drum
205
+ Essentials, SONiVOX Orchestral Brass/Strings/Woodwinds, Grand
206
+ Piano, Synth Essentials, Session Drums Club + Studio, Core
207
+ Library) with consistent Essence/Scores/Top/Use/Avoid structure
208
+
209
+ **Deepened shallow enrichments** (T8):
210
+ - Added `pairs_well_with` + expanded `gotchas` +
211
+ `signature_techniques` for: `snipper`, `bell_tower`,
212
+ `performer`, `vector_map`, `filler`
213
+
214
+ ### Concept surface — knowledge the LLM can reason over
215
+
216
+ Late-v1.17 audit found LivePilot's concept-vs-recipe ratio was already
217
+ healthy (sample-philosophy.md, sound-design-deep.md, per-device
218
+ `signature_techniques`, aesthetic-tagged `character_tags`), but two gaps
219
+ were worth closing before the release: native-synth enrichments heavy
220
+ on `starter_recipes` but thin on `signature_techniques`, and no
221
+ structured artist/genre → device-vocabulary bridge.
222
+
223
+ Added:
224
+
225
+ - **`livepilot/skills/livepilot-core/references/artist-vocabularies.md`** —
226
+ ~25 producers (Villalobos, Hawtin/Plastikman, Basic Channel, Gas,
227
+ Basinski, Stars of the Lid, Hecker, Aphex, Autechre, OPN, Arca,
228
+ Dilla, Premier, Madlib, Burial, Mala, Jeff Mills, Moodymann, Daft
229
+ Punk, Rashad, Photek, Com Truise, Boards of Canada, etc.) with
230
+ four-field structured entries (sonic fingerprint / reach for /
231
+ avoid / key techniques). Each entry cross-references
232
+ `signature_techniques` in per-device YAML or technique names in
233
+ `sample-techniques.md` / `sound-design-deep.md` — no duplication,
234
+ just a translation layer from producer names to LivePilot devices
235
+ - **`livepilot/skills/livepilot-core/references/genre-vocabularies.md`** —
236
+ 15 genres (microhouse, dub_techno, deep_minimal, minimal_techno,
237
+ ambient, idm, modern_classical, hip_hop, trap, dubstep, house,
238
+ dnb, garage, experimental, synthwave) with tempo / kick / bass /
239
+ percussion / harmonic / texture / reach-for / avoid structure.
240
+ Read-before-tool-selection reference for genre-driven workflows
241
+ - **Native-synth `signature_techniques` backfill** — 15 YAMLs that
242
+ had starter_recipes but no aesthetic-level guidance now have 3
243
+ techniques each, tagged to known producers (Hawtin subtractive pad,
244
+ 303 acid bass, Reese bass for DnB, J Dilla micro-timed kit, Villalobos
245
+ sub-bass layer, Basinski tape degradation, Tim Hecker grain cloud,
246
+ etc.). Files updated: analog, operator, wavetable, drift, collision,
247
+ tension, electric, simpler, sampler, bass, poli, emit, meld,
248
+ vector_fm, vector_grain
249
+ - **`mcp_server/atlas/device_techniques_index.json`** — auto-generated
250
+ reverse-index of 146 device→technique cross-references across 58
251
+ devices, mined from per-device `signature_techniques` +
252
+ `sample-techniques.md` + `sound-design-deep.md`
253
+
254
+ ### Docs
255
+
256
+ - `docs/2026-04-22-release-verification.md` — end-to-end
257
+ verification report with live-verified evidence per task
258
+ - `docs/2026-04-22-splice-https-capture-recipe.md` — mitmproxy
259
+ runbook for capturing additional Splice GraphQL operations
260
+ - `docs/2026-04-22-live-api-probe-arrangement-automation.md` —
261
+ design rationale for the T5 two-phase split
262
+ - `docs/2026-04-22-sub-low-band-max-workflow.md` — Max
263
+ editor runbook for future filter-bank edits
264
+ - `docs/manual/index.md` — rewrote domain map from source-of-truth
265
+ per-domain counts (was drifting 30+ entries). Added 7 missing
266
+ domains (scales, grooves, take_lanes, follow_actions, miditool,
267
+ diagnostics, synthesis_brain)
268
+ - `docs/manual/tool-reference.md` — new sections for Device Atlas,
269
+ Sample Engine & Splice, Diagnostics; added v1.17 tools
270
+ (`atlas_pack_info`, `set_arrangement_automation_via_session_record`,
271
+ `splice_http_diagnose`, `splice_describe_sound` LIVE,
272
+ `splice_generate_variation` LIVE); added `add_drum_rack_pad` +
273
+ `verify_device_alive` + `verify_all_devices_health` that were
274
+ missing since v1.16
275
+ - `docs/manual/tool-catalog.md` — replaced hand-curated drifting
276
+ version with single auto-generated file (run
277
+ `python3 scripts/generate_tool_catalog.py > docs/manual/tool-catalog.md`).
278
+ Retired `docs/manual/tool-catalog-generated.md` (duplicate
279
+ with -generated suffix)
280
+ - **Deleted**: `docs/TOOL_REFERENCE.md` (v1.7-era, 317 tools /
281
+ 43 domains — misleadingly stale)
282
+ - **Archived**: `docs/manual/release-smoke-board.md` → `docs/archive/release-smoke-board-v1.10-era.md`
283
+
284
+ ### Internal
285
+
286
+ - `mcp_server/splice_client/graphql_queries/` — new directory,
287
+ holds captured `.graphql` query strings, loaded lazily via
288
+ `_load_graphql_query()` with caching
289
+ - `docs/research/splice-api-capture/` — gitignored local archive
290
+ of 4 operation captures (request + response pairs):
291
+ `SamplesSearch`, `SoundsSearchAutocomplete`,
292
+ `RefreshSamplePreview`, `AssetSimilarSoundsQuery`
293
+ - 5 additional GraphQL operations captured but not wired —
294
+ candidates for future tools: `DesktopPackSearch`,
295
+ `SampleAssetSidebarQuery`, `BrowseCarousels`,
296
+ `CreditsStoreQuery`, `UserService`
297
+
298
+ ### Known non-blockers
299
+
300
+ - Splice Search-with-Sound (audio-file reference search) is
301
+ retired — feature not exposed in Splice desktop v5.4.9's UI,
302
+ user handles it manually. Recipe preserved if a future Splice
303
+ build re-exposes it.
304
+ - T5 live end-to-end verification in a real Ableton session
305
+ deferred — contract tests (17) lock the protocol; first real
306
+ invocation will confirm Live LOM assumptions (classic
307
+ v1.16.0 → v1.16.1 pattern — any surprises fix in one edit).
308
+ - `splice_http_diagnose` token-availability probe reported a
309
+ false negative pre-1.17 (walked the wrong context path); fixed
310
+ to use `ctx.lifespan_context["splice_client"]` + actually call
311
+ `fetch_session_token`.
312
+
313
+
3
314
  ## 1.16.1 — Post-publish live-verification bug sweep (April 22 2026)
4
315
 
5
316
  Three rounds of live verification after 1.16.0 shipped caught five
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  <p align="center">
19
19
  An agentic production system for Ableton Live 12.<br>
20
- 422 tools. 52 domains. Device atlas. Plan-aware Splice integration. Auto-composition. Spectral perception. Technique memory. Drum-rack pad builder. Live dead-device detection.
20
+ 426 tools. 52 domains. Device atlas. Plan-aware Splice integration. Auto-composition. Spectral perception. Technique memory. Drum-rack pad builder. Live dead-device detection.
21
21
  </p>
22
22
 
23
23
  <br>
@@ -33,16 +33,17 @@
33
33
 
34
34
  ## What LivePilot Does
35
35
 
36
- Most MCP servers are tool collections — they execute commands. LivePilot is an **agentic production system**. It has six layers that work together:
36
+ Most MCP servers are tool collections — they execute commands. LivePilot is an **agentic production system**. It has seven layers that work together:
37
37
 
38
38
  | Layer | What it provides |
39
39
  |-------|-----------------|
40
40
  | **Deterministic Tools** | Direct control: transport, tracks, clips, notes, devices, scenes, mixing, arrangement, browser, automation |
41
- | **Device Atlas** | Knowledge of every device in Ableton's library — 1305 devices indexed by name, URI, category, tag, and genre. 107 enriched with sonic intelligence. 683 drum kits mapped |
42
- | **Sample Engine** | Three-source sample intelligence Ableton's browser, your filesystem, and Splice's catalog (plan-aware: Ableton Live plan uses daily quota, Sounds+/Creator uses credits, free samples bypass both). 6 fitness critics. 29 processing techniques. Collections, presets, preview-URL audition, HTTPS bridge scaffolding for Describe-a-Sound + Variations |
43
- | **Spectral Perception** | Real-time ears via M4L 8-band FFT, RMS/peak metering, Krumhansl-Schmuckler key detection, pitch tracking. Closes the feedback loop so the AI hears its own changes |
41
+ | **Device Atlas** | Knowledge of every device in Ableton's library — 1305 devices indexed by name, URI, category, tag, genre, and pack (641 pack-indexed). 120 enriched with sonic intelligence (47 with aesthetic-tagged `signature_techniques`). 683 drum kits mapped. **Free-text `atlas_describe_chain`** ("a granular pad like Tim Hecker") and **reverse-lookup `atlas_techniques_for_device`** (what techniques reference this device?) added in v1.17 |
42
+ | **Concept Surface** | **New in v1.17.** Two reference files let the LLM's training translate into LivePilot: `artist-vocabularies.md` maps ~25 producers (Villalobos, Hawtin, Basic Channel, Gas, Basinski, Hecker, Aphex, Autechre, Dilla, Burial, Henke, Daft Punk, …) to `reach_for` / `avoid` / `key_techniques`; `genre-vocabularies.md` maps 15 genres to tempo / kick / bass / percussion / harmonic / texture / devices. 146 cross-references between devices and techniques. The LLM reads "sound like Gas" and gets a concrete device chain, not guesswork |
43
+ | **Sample Engine** | Three-source sample intelligenceAbleton's browser, your filesystem, and Splice's catalog (plan-aware: Ableton Live plan uses daily quota, Sounds+/Creator uses credits, free samples bypass both). 6 fitness critics. 29 processing techniques. Collections, presets, preview-URL audition, **LIVE Describe-a-Sound + Variations via Splice GraphQL (v1.17)** |
44
+ | **Spectral Perception** | Real-time ears via M4L — **9-band FFT (v1.17+, sub_low split at 20-60 Hz)**, RMS/peak metering, Krumhansl-Schmuckler key detection, pitch tracking, FluCoMa mel/chroma/onset. Closes the feedback loop so the AI hears its own changes |
44
45
  | **Technique Memory** | Persistent library of production decisions. Save a beat pattern, device chain, or mix template. Recall by mood, genre, or texture across sessions |
45
- | **Creative Intelligence** | 12 engines that understand song identity, learn your taste, diagnose stuck sessions, generate creative options, and evaluate results before claiming success |
46
+ | **Creative Intelligence** | A dozen engines that understand song identity, learn your taste, diagnose stuck sessions, generate creative options, and evaluate results before claiming success |
46
47
 
47
48
  <br>
48
49
 
@@ -56,9 +57,9 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
56
57
  │ KNOWLEDGE PERCEPTION MEMORY │
57
58
  │ ────────────── ────────────── ────────────── │
58
59
  │ │
59
- │ Device Atlas 8-band FFT recall by mood, │
60
+ │ Device Atlas 9-band FFT recall by mood, │
60
61
  │ 1305 devices RMS / peak genre, texture │
61
- 107 enriched pitch tracking 29 techniques │
62
+ 120 enriched pitch tracking 29 techniques │
62
63
  │ 683 drum kits key detection replay into session │
63
64
  │ │
64
65
  │ Sample Engine Corpus Intelligence Taste Graph │
@@ -79,7 +80,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
79
80
  │ └─────────────────┼──────────────────┘ │
80
81
  │ ▼ │
81
82
  │ ┌─────────────────┐ │
82
- │ │ 422 MCP Tools │ │
83
+ │ │ 426 MCP Tools │ │
83
84
  │ │ 52 domains │ │
84
85
  │ └────────┬────────┘ │
85
86
  │ │ │
@@ -102,7 +103,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
102
103
 
103
104
  **M4L Bridge** (`m4l_device/`) — Optional Max for Live Audio Effect on the master track. Provides deep LOM access through Max's LiveAPI that the ControlSurface API can't reach. UDP 9880 (M4L to server) carries spectral data and LiveAPI responses. OSC 9881 (server to M4L) sends commands. The 32 spectral/analyzer tools strictly require the bridge; device and sample tools that call the bridge also have graceful fallbacks, so core functionality works without it. Backed by 30 bridge commands for hidden parameters, Simpler internals, warp markers, display values, and Simpler warp / Compressor sidechain writes that live on child objects Python can't reach.
104
105
 
105
- **Device Atlas** (`mcp_server/atlas/`) — In-memory indexed JSON database. 1305 devices with browser URIs, 107 enriched with YAML sonic intelligence profiles (mood, genre, texture, recommended chains). 6 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre. The AI never hallucinates a device name or preset — it always resolves against the atlas first.
106
+ **Device Atlas** (`mcp_server/atlas/`) — In-memory indexed JSON database. 1305 devices with browser URIs, 120 enriched with YAML sonic intelligence profiles (mood, genre, texture, recommended chains). 6 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre. The AI never hallucinates a device name or preset — it always resolves against the atlas first.
106
107
 
107
108
  **Sample Engine** (`mcp_server/sample_engine/`) — Searches three sources simultaneously: BrowserSource (Ableton's library), SpliceSource (local Splice catalog via SQLite), FilesystemSource (user directories). Every result passes through a 6-critic fitness battery (key, tempo, spectral, genre, mood, technical). 29 processing techniques (Surgeon precision vs. Alchemist experimentation). Builds complete sample processing plans with warp, slice, and effect recommendations.
108
109
 
@@ -120,7 +121,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
120
121
 
121
122
  ## The Intelligence Layer
122
123
 
123
- 12 engines sit on top of the 422 tools. They give the AI musical judgment, not just musical execution.
124
+ 12 engines sit on top of the 426 tools. They give the AI musical judgment, not just musical execution.
124
125
 
125
126
  ### SongBrain — What the Song Is
126
127
 
@@ -172,7 +173,7 @@ Every engine follows: **measure before → act → measure after → compare**.
172
173
 
173
174
  ## Tools
174
175
 
175
- 422 tools across 52 domains. Highlights below — [full catalog here](docs/manual/tool-catalog.md).
176
+ 426 tools across 52 domains. Highlights below — [full catalog here](docs/manual/tool-catalog.md).
176
177
 
177
178
  <br>
178
179
 
@@ -232,7 +233,7 @@ The atlas is an in-memory indexed database of Ableton's entire device library.
232
233
 
233
234
  ```
234
235
  1305 devices total
235
- 107 enriched with sonic intelligence (mood, genre, texture, chains)
236
+ 120 enriched with sonic intelligence (mood, genre, texture, chains)
236
237
  683 drum kits mapped with note assignments
237
238
  6 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre
238
239
  ```
@@ -360,7 +361,7 @@ The V2 intelligence layer. These tools analyze, diagnose, plan, evaluate, and le
360
361
  | Creative Constraints | 5 | constraint activation, reference-inspired variants |
361
362
  | Preview Studio | 5 | variant creation, preview rendering, comparison, commit |
362
363
 
363
- > **[View all 422 tools →](docs/manual/tool-catalog.md)**
364
+ > **[View all 426 tools →](docs/manual/tool-catalog.md)**
364
365
 
365
366
  <br>
366
367
 
@@ -587,7 +588,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for architecture details, code guidelines
587
588
 
588
589
  | Document | What's inside |
589
590
  |----------|---------------|
590
- | [Manual](docs/manual/index.md) | Complete reference: architecture, all 422 tools, workflows |
591
+ | [Manual](docs/manual/index.md) | Complete reference: architecture, all 426 tools, workflows |
591
592
  | [Intelligence Layer](docs/manual/intelligence.md) | How the 12 engines connect — conductor, moves, preview, evaluation |
592
593
  | [Device Atlas](docs/manual/device-atlas.md) | 1305 devices indexed — search, suggest, chain building |
593
594
  | [Samples & Slicing](docs/manual/samples.md) | 3-source search, fitness critics, slice workflows |
@@ -42,6 +42,19 @@ function loadManifest() {
42
42
  return JSON.parse(fs.readFileSync(SOURCE_MANIFEST, "utf-8"));
43
43
  }
44
44
 
45
+ function writeLocalMcpConfig(destDir) {
46
+ const file = path.join(destDir, ".mcp.json");
47
+ const config = {
48
+ mcpServers: {
49
+ livepilot: {
50
+ command: process.execPath,
51
+ args: [path.join(ROOT, "bin", "livepilot.js")],
52
+ },
53
+ },
54
+ };
55
+ fs.writeFileSync(file, JSON.stringify(config, null, 2) + "\n");
56
+ }
57
+
45
58
  function ensureMarketplace(pluginName) {
46
59
  const file = marketplacePath();
47
60
  let marketplace = {
@@ -115,6 +128,7 @@ function installCodexPlugin() {
115
128
  fs.mkdirSync(path.dirname(destDir), { recursive: true });
116
129
  fs.rmSync(destDir, { recursive: true, force: true });
117
130
  copyDirSync(SOURCE_DIR, destDir);
131
+ writeLocalMcpConfig(destDir);
118
132
 
119
133
  console.log("Done! Next steps:");
120
134
  console.log(" 1. Open or refresh Codex");
Binary file
@@ -95,7 +95,7 @@ function anything() {
95
95
  function dispatch(cmd, args) {
96
96
  switch(cmd) {
97
97
  case "ping":
98
- send_response({"ok": true, "version": "1.16.1"});
98
+ send_response({"ok": true, "version": "1.17.1"});
99
99
  break;
100
100
  case "get_params":
101
101
  cmd_get_params(args);
@@ -1,2 +1,2 @@
1
1
  """LivePilot MCP Server — bridges MCP protocol to Ableton Live."""
2
- __version__ = "1.16.1"
2
+ __version__ = "1.17.1"
@@ -28,6 +28,7 @@ class AtlasManager:
28
28
  self._by_category: Dict[str, List[Dict[str, Any]]] = {}
29
29
  self._by_tag: Dict[str, List[Dict[str, Any]]] = {}
30
30
  self._by_genre: Dict[str, List[Dict[str, Any]]] = {}
31
+ self._by_pack: Dict[str, List[Dict[str, Any]]] = {}
31
32
 
32
33
  for dev in self._devices:
33
34
  dev_id = dev.get("id", "")
@@ -55,6 +56,30 @@ class AtlasManager:
55
56
  self._by_genre.setdefault(genre.lower(), []).append(dev)
56
57
  for genre in dev.get("genres", {}).get("secondary", []):
57
58
  self._by_genre.setdefault(genre.lower(), []).append(dev)
59
+ # Also read the enriched genre_affinity field, which is where
60
+ # curated YAML entries land after merge (scanners emit `genres`,
61
+ # enrichments emit `genre_affinity` — both must feed the index
62
+ # or new minimal/microhouse/dub_techno tags would never surface).
63
+ aff = dev.get("genre_affinity", {}) or {}
64
+ for genre in aff.get("primary", []) if isinstance(aff, dict) else []:
65
+ self._by_genre.setdefault(str(genre).lower(), []).append(dev)
66
+ for genre in aff.get("secondary", []) if isinstance(aff, dict) else []:
67
+ self._by_genre.setdefault(str(genre).lower(), []).append(dev)
68
+
69
+ # Pack index — enriched devices declare `pack:` in YAML. Native
70
+ # Live devices without an explicit pack default to "Core Library"
71
+ # so the index covers everything shipped with the stock install.
72
+ pack_name = dev.get("pack")
73
+ if not pack_name and dev.get("source") in (None, "native", "browser"):
74
+ # Heuristic: if we have no explicit pack and the scan source
75
+ # is the built-in browser, treat as Core Library. Don't fake
76
+ # a pack for plugins/user samples where the source isn't the
77
+ # stock library.
78
+ if dev_category in ("instruments", "audio_effects",
79
+ "midi_effects", "max_for_live"):
80
+ pack_name = "Core Library"
81
+ if pack_name:
82
+ self._by_pack.setdefault(pack_name, []).append(dev)
58
83
 
59
84
  # ── Properties ──────────────────────────────────────────────────
60
85
 
@@ -83,9 +108,69 @@ class AtlasManager:
83
108
  "by_category": len(self._by_category),
84
109
  "by_tag": len(self._by_tag),
85
110
  "by_genre": len(self._by_genre),
111
+ "by_pack": len(self._by_pack),
86
112
  },
87
113
  }
88
114
 
115
+ # ── Pack lookup ────────────────────────────────────────────────
116
+ def pack_info(self, pack_name: str) -> Dict[str, Any]:
117
+ """Return summary of a pack — device list + enrichment coverage.
118
+
119
+ Matches the pack name case-insensitively; the index stores the
120
+ canonical casing from the YAML (e.g. "Core Library", "Drone Lab").
121
+ """
122
+ if not pack_name:
123
+ return {"pack": "", "device_count": 0, "enriched_count": 0,
124
+ "devices": []}
125
+
126
+ target = pack_name.strip().lower()
127
+ # Find canonical name
128
+ canonical = None
129
+ for name in self._by_pack.keys():
130
+ if name.lower() == target:
131
+ canonical = name
132
+ break
133
+
134
+ if canonical is None:
135
+ return {
136
+ "pack": pack_name,
137
+ "device_count": 0,
138
+ "enriched_count": 0,
139
+ "devices": [],
140
+ "available_packs": sorted(self._by_pack.keys()),
141
+ }
142
+
143
+ devices = self._by_pack[canonical]
144
+ enriched = [d for d in devices if d.get("enriched")]
145
+ return {
146
+ "pack": canonical,
147
+ "device_count": len(devices),
148
+ "enriched_count": len(enriched),
149
+ "devices": [
150
+ {
151
+ "id": d.get("id", ""),
152
+ "name": d.get("name", ""),
153
+ "category": d.get("category", ""),
154
+ "enriched": bool(d.get("enriched")),
155
+ "uri": d.get("uri", ""),
156
+ }
157
+ for d in devices
158
+ ],
159
+ }
160
+
161
+ def list_packs(self) -> List[Dict[str, Any]]:
162
+ """All known packs with device counts, sorted by size descending."""
163
+ packs = [
164
+ {
165
+ "name": name,
166
+ "device_count": len(devs),
167
+ "enriched_count": sum(1 for d in devs if d.get("enriched")),
168
+ }
169
+ for name, devs in self._by_pack.items()
170
+ ]
171
+ packs.sort(key=lambda p: -p["device_count"])
172
+ return packs
173
+
89
174
  # ── Lookup ──────────────────────────────────────────────────────
90
175
 
91
176
  def lookup(self, name_or_id: str) -> Optional[Dict[str, Any]]: