livepilot 1.26.0 → 1.26.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 (181) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +1 -1
  3. package/installer/codex.js +87 -9
  4. package/livepilot/.Codex-plugin/plugin.json +8 -0
  5. package/livepilot/.claude-plugin/plugin.json +8 -0
  6. package/livepilot/.mcp.json +8 -0
  7. package/livepilot/agents/livepilot-producer/AGENT.md +314 -0
  8. package/livepilot/commands/arrange.md +47 -0
  9. package/livepilot/commands/beat.md +81 -0
  10. package/livepilot/commands/evaluate.md +49 -0
  11. package/livepilot/commands/memory.md +22 -0
  12. package/livepilot/commands/mix.md +47 -0
  13. package/livepilot/commands/perform.md +42 -0
  14. package/livepilot/commands/session.md +13 -0
  15. package/livepilot/commands/sounddesign.md +58 -0
  16. package/livepilot/rubrics/default_preset_check.md +82 -0
  17. package/livepilot/rubrics/layer_accumulation.md +79 -0
  18. package/livepilot/rubrics/layer_precision.md +79 -0
  19. package/livepilot/rubrics/modulation_presence.md +63 -0
  20. package/livepilot/rubrics/sound_design_depth.md +40 -0
  21. package/livepilot/skills/livepilot-arrangement/SKILL.md +164 -0
  22. package/livepilot/skills/livepilot-composition-engine/SKILL.md +151 -0
  23. package/livepilot/skills/livepilot-composition-engine/references/form-patterns.md +97 -0
  24. package/livepilot/skills/livepilot-composition-engine/references/transition-archetypes.md +102 -0
  25. package/livepilot/skills/livepilot-core/SKILL.md +261 -0
  26. package/livepilot/skills/livepilot-core/references/ableton-workflow-patterns.md +831 -0
  27. package/livepilot/skills/livepilot-core/references/affordances/_schema.md +160 -0
  28. package/livepilot/skills/livepilot-core/references/affordances/devices/auto-filter.yaml +133 -0
  29. package/livepilot/skills/livepilot-core/references/affordances/devices/chorus-ensemble.yaml +91 -0
  30. package/livepilot/skills/livepilot-core/references/affordances/devices/compressor.yaml +98 -0
  31. package/livepilot/skills/livepilot-core/references/affordances/devices/convolution-reverb.yaml +113 -0
  32. package/livepilot/skills/livepilot-core/references/affordances/devices/corpus.yaml +84 -0
  33. package/livepilot/skills/livepilot-core/references/affordances/devices/drift.yaml +105 -0
  34. package/livepilot/skills/livepilot-core/references/affordances/devices/echo.yaml +108 -0
  35. package/livepilot/skills/livepilot-core/references/affordances/devices/eq-eight.yaml +95 -0
  36. package/livepilot/skills/livepilot-core/references/affordances/devices/glue-compressor.yaml +88 -0
  37. package/livepilot/skills/livepilot-core/references/affordances/devices/granulator-iii.yaml +104 -0
  38. package/livepilot/skills/livepilot-core/references/affordances/devices/hybrid-reverb.yaml +83 -0
  39. package/livepilot/skills/livepilot-core/references/affordances/devices/operator.yaml +98 -0
  40. package/livepilot/skills/livepilot-core/references/affordances/devices/ping-pong-delay.yaml +104 -0
  41. package/livepilot/skills/livepilot-core/references/affordances/devices/poli.yaml +98 -0
  42. package/livepilot/skills/livepilot-core/references/affordances/devices/saturator.yaml +98 -0
  43. package/livepilot/skills/livepilot-core/references/affordances/devices/shifter.yaml +77 -0
  44. package/livepilot/skills/livepilot-core/references/affordances/devices/simpler.yaml +113 -0
  45. package/livepilot/skills/livepilot-core/references/affordances/devices/utility.yaml +95 -0
  46. package/livepilot/skills/livepilot-core/references/affordances/devices/vinyl-distortion.yaml +92 -0
  47. package/livepilot/skills/livepilot-core/references/affordances/devices/wavetable.yaml +98 -0
  48. package/livepilot/skills/livepilot-core/references/artist-vocabularies.md +389 -0
  49. package/livepilot/skills/livepilot-core/references/automation-atlas.md +272 -0
  50. package/livepilot/skills/livepilot-core/references/concepts/_schema.md +158 -0
  51. package/livepilot/skills/livepilot-core/references/concepts/artists/akufen.yaml +116 -0
  52. package/livepilot/skills/livepilot-core/references/concepts/artists/aphex-twin.yaml +133 -0
  53. package/livepilot/skills/livepilot-core/references/concepts/artists/arca-sophie.yaml +131 -0
  54. package/livepilot/skills/livepilot-core/references/concepts/artists/autechre.yaml +130 -0
  55. package/livepilot/skills/livepilot-core/references/concepts/artists/basic-channel.yaml +140 -0
  56. package/livepilot/skills/livepilot-core/references/concepts/artists/basinski.yaml +126 -0
  57. package/livepilot/skills/livepilot-core/references/concepts/artists/boards-of-canada.yaml +124 -0
  58. package/livepilot/skills/livepilot-core/references/concepts/artists/burial.yaml +127 -0
  59. package/livepilot/skills/livepilot-core/references/concepts/artists/com-truise-tycho.yaml +121 -0
  60. package/livepilot/skills/livepilot-core/references/concepts/artists/daft-punk.yaml +117 -0
  61. package/livepilot/skills/livepilot-core/references/concepts/artists/dj-premier-rza.yaml +119 -0
  62. package/livepilot/skills/livepilot-core/references/concepts/artists/gas.yaml +134 -0
  63. package/livepilot/skills/livepilot-core/references/concepts/artists/hawtin.yaml +127 -0
  64. package/livepilot/skills/livepilot-core/references/concepts/artists/isolee-luomo.yaml +130 -0
  65. package/livepilot/skills/livepilot-core/references/concepts/artists/j-dilla.yaml +133 -0
  66. package/livepilot/skills/livepilot-core/references/concepts/artists/jeff-mills.yaml +120 -0
  67. package/livepilot/skills/livepilot-core/references/concepts/artists/johannsson-richter.yaml +132 -0
  68. package/livepilot/skills/livepilot-core/references/concepts/artists/madlib.yaml +124 -0
  69. package/livepilot/skills/livepilot-core/references/concepts/artists/moodymann-theo-parrish.yaml +121 -0
  70. package/livepilot/skills/livepilot-core/references/concepts/artists/oneohtrix-point-never.yaml +126 -0
  71. package/livepilot/skills/livepilot-core/references/concepts/artists/photek-source-direct.yaml +120 -0
  72. package/livepilot/skills/livepilot-core/references/concepts/artists/rashad-spinn-traxman.yaml +122 -0
  73. package/livepilot/skills/livepilot-core/references/concepts/artists/robert-henke.yaml +113 -0
  74. package/livepilot/skills/livepilot-core/references/concepts/artists/shackleton.yaml +124 -0
  75. package/livepilot/skills/livepilot-core/references/concepts/artists/skream-mala.yaml +119 -0
  76. package/livepilot/skills/livepilot-core/references/concepts/artists/stars-of-the-lid.yaml +119 -0
  77. package/livepilot/skills/livepilot-core/references/concepts/artists/tim-hecker.yaml +122 -0
  78. package/livepilot/skills/livepilot-core/references/concepts/artists/villalobos.yaml +135 -0
  79. package/livepilot/skills/livepilot-core/references/concepts/genres/ambient.yaml +137 -0
  80. package/livepilot/skills/livepilot-core/references/concepts/genres/boom_bap.yaml +124 -0
  81. package/livepilot/skills/livepilot-core/references/concepts/genres/deep-minimal.yaml +130 -0
  82. package/livepilot/skills/livepilot-core/references/concepts/genres/deep_house.yaml +130 -0
  83. package/livepilot/skills/livepilot-core/references/concepts/genres/detroit_techno.yaml +116 -0
  84. package/livepilot/skills/livepilot-core/references/concepts/genres/disco.yaml +123 -0
  85. package/livepilot/skills/livepilot-core/references/concepts/genres/downtempo.yaml +129 -0
  86. package/livepilot/skills/livepilot-core/references/concepts/genres/drone.yaml +133 -0
  87. package/livepilot/skills/livepilot-core/references/concepts/genres/drum-and-bass.yaml +119 -0
  88. package/livepilot/skills/livepilot-core/references/concepts/genres/dub-techno.yaml +132 -0
  89. package/livepilot/skills/livepilot-core/references/concepts/genres/dub.yaml +129 -0
  90. package/livepilot/skills/livepilot-core/references/concepts/genres/dubstep.yaml +120 -0
  91. package/livepilot/skills/livepilot-core/references/concepts/genres/experimental.yaml +136 -0
  92. package/livepilot/skills/livepilot-core/references/concepts/genres/footwork.yaml +119 -0
  93. package/livepilot/skills/livepilot-core/references/concepts/genres/hip-hop.yaml +132 -0
  94. package/livepilot/skills/livepilot-core/references/concepts/genres/house.yaml +126 -0
  95. package/livepilot/skills/livepilot-core/references/concepts/genres/hyperpop.yaml +128 -0
  96. package/livepilot/skills/livepilot-core/references/concepts/genres/idm.yaml +134 -0
  97. package/livepilot/skills/livepilot-core/references/concepts/genres/lo_fi.yaml +129 -0
  98. package/livepilot/skills/livepilot-core/references/concepts/genres/microhouse.yaml +138 -0
  99. package/livepilot/skills/livepilot-core/references/concepts/genres/minimal-techno.yaml +116 -0
  100. package/livepilot/skills/livepilot-core/references/concepts/genres/modern-classical.yaml +123 -0
  101. package/livepilot/skills/livepilot-core/references/concepts/genres/soul.yaml +125 -0
  102. package/livepilot/skills/livepilot-core/references/concepts/genres/synthwave.yaml +123 -0
  103. package/livepilot/skills/livepilot-core/references/concepts/genres/techno.yaml +123 -0
  104. package/livepilot/skills/livepilot-core/references/concepts/genres/trap.yaml +120 -0
  105. package/livepilot/skills/livepilot-core/references/concepts/genres/uk-garage.yaml +121 -0
  106. package/livepilot/skills/livepilot-core/references/device-atlas/00-index.md +110 -0
  107. package/livepilot/skills/livepilot-core/references/device-atlas/distortion-and-character.md +687 -0
  108. package/livepilot/skills/livepilot-core/references/device-atlas/drums-and-percussion.md +753 -0
  109. package/livepilot/skills/livepilot-core/references/device-atlas/dynamics-and-punch.md +525 -0
  110. package/livepilot/skills/livepilot-core/references/device-atlas/eq-and-filtering.md +402 -0
  111. package/livepilot/skills/livepilot-core/references/device-atlas/midi-tools.md +963 -0
  112. package/livepilot/skills/livepilot-core/references/device-atlas/movement-and-modulation.md +874 -0
  113. package/livepilot/skills/livepilot-core/references/device-atlas/space-and-depth.md +571 -0
  114. package/livepilot/skills/livepilot-core/references/device-atlas/spectral-and-weird.md +714 -0
  115. package/livepilot/skills/livepilot-core/references/device-atlas/synths-native.md +953 -0
  116. package/livepilot/skills/livepilot-core/references/device-knowledge/00-index.md +34 -0
  117. package/livepilot/skills/livepilot-core/references/device-knowledge/automation-as-music.md +204 -0
  118. package/livepilot/skills/livepilot-core/references/device-knowledge/chains-genre.md +173 -0
  119. package/livepilot/skills/livepilot-core/references/device-knowledge/creative-thinking.md +211 -0
  120. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-distortion.md +188 -0
  121. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-space.md +162 -0
  122. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-spectral.md +229 -0
  123. package/livepilot/skills/livepilot-core/references/device-knowledge/instruments-synths.md +243 -0
  124. package/livepilot/skills/livepilot-core/references/genre-vocabularies.md +382 -0
  125. package/livepilot/skills/livepilot-core/references/m4l-devices.md +352 -0
  126. package/livepilot/skills/livepilot-core/references/memory-guide.md +178 -0
  127. package/livepilot/skills/livepilot-core/references/midi-recipes.md +402 -0
  128. package/livepilot/skills/livepilot-core/references/mixing-patterns.md +578 -0
  129. package/livepilot/skills/livepilot-core/references/overview.md +300 -0
  130. package/livepilot/skills/livepilot-core/references/pack-knowledge.md +319 -0
  131. package/livepilot/skills/livepilot-core/references/sample-manipulation.md +724 -0
  132. package/livepilot/skills/livepilot-core/references/sound-design-deep.md +140 -0
  133. package/livepilot/skills/livepilot-core/references/sound-design.md +393 -0
  134. package/livepilot/skills/livepilot-corpus-builder/SKILL.md +379 -0
  135. package/livepilot/skills/livepilot-creative-director/SKILL.md +455 -0
  136. package/livepilot/skills/livepilot-creative-director/references/anti-repetition-rules.md +214 -0
  137. package/livepilot/skills/livepilot-creative-director/references/creative-brief-template.md +222 -0
  138. package/livepilot/skills/livepilot-creative-director/references/hybrid-compilation.md +185 -0
  139. package/livepilot/skills/livepilot-creative-director/references/move-family-diversity-rule.md +258 -0
  140. package/livepilot/skills/livepilot-creative-director/references/phase-6-execution.md +409 -0
  141. package/livepilot/skills/livepilot-creative-director/references/the-four-move-rule.md +192 -0
  142. package/livepilot/skills/livepilot-devices/SKILL.md +213 -0
  143. package/livepilot/skills/livepilot-devices/references/load_browser_item-uri-grammar.md +82 -0
  144. package/livepilot/skills/livepilot-evaluation/SKILL.md +195 -0
  145. package/livepilot/skills/livepilot-evaluation/references/capability-modes.md +176 -0
  146. package/livepilot/skills/livepilot-evaluation/references/evaluation-contracts.md +121 -0
  147. package/livepilot/skills/livepilot-evaluation/references/memory-promotion.md +110 -0
  148. package/livepilot/skills/livepilot-mix-engine/SKILL.md +136 -0
  149. package/livepilot/skills/livepilot-mix-engine/references/mix-critics.md +143 -0
  150. package/livepilot/skills/livepilot-mix-engine/references/mix-moves.md +105 -0
  151. package/livepilot/skills/livepilot-mixing/SKILL.md +157 -0
  152. package/livepilot/skills/livepilot-notes/SKILL.md +130 -0
  153. package/livepilot/skills/livepilot-performance-engine/SKILL.md +122 -0
  154. package/livepilot/skills/livepilot-performance-engine/references/performance-safety.md +98 -0
  155. package/livepilot/skills/livepilot-release/SKILL.md +151 -0
  156. package/livepilot/skills/livepilot-sample-engine/SKILL.md +117 -0
  157. package/livepilot/skills/livepilot-sample-engine/references/sample-critics.md +87 -0
  158. package/livepilot/skills/livepilot-sample-engine/references/sample-philosophy.md +51 -0
  159. package/livepilot/skills/livepilot-sample-engine/references/sample-techniques.md +131 -0
  160. package/livepilot/skills/livepilot-sound-design-engine/SKILL.md +225 -0
  161. package/livepilot/skills/livepilot-sound-design-engine/references/patch-model.md +119 -0
  162. package/livepilot/skills/livepilot-sound-design-engine/references/sound-design-critics.md +118 -0
  163. package/livepilot/skills/livepilot-wonder/SKILL.md +143 -0
  164. package/m4l_device/LivePilot_Analyzer.amxd +0 -0
  165. package/m4l_device/LivePilot_Elektron.amxd +0 -0
  166. package/m4l_device/LivePilot_Elektron.maxpat +758 -0
  167. package/m4l_device/livepilot_bridge.js +1 -1
  168. package/m4l_device/livepilot_elektron_bridge.js +82 -0
  169. package/mcp_server/__init__.py +1 -1
  170. package/mcp_server/composer/develop/apply.py +1 -1
  171. package/mcp_server/composer/full/apply.py +32 -6
  172. package/mcp_server/m4l_bridge.py +5 -0
  173. package/mcp_server/runtime/execution_router.py +6 -0
  174. package/mcp_server/runtime/mcp_dispatch.py +18 -0
  175. package/mcp_server/runtime/remote_commands.py +2 -0
  176. package/mcp_server/server.py +11 -7
  177. package/package.json +20 -5
  178. package/remote_script/LivePilot/__init__.py +1 -1
  179. package/remote_script/LivePilot/server.py +63 -2
  180. package/requirements.txt +3 -3
  181. package/server.json +3 -3
@@ -34,7 +34,7 @@ outlets = 2; // 0: to udpsend (responses), 1: to buffer~/status
34
34
  // Single source of truth for the bridge version — bumped alongside the
35
35
  // rest of the release manifest. Surfaced in the UI via messnamed("livepilot_version", ...)
36
36
  // so the frozen .amxd visibly reports which build it was last exported from.
37
- var VERSION = "1.26.0";
37
+ var VERSION = "1.26.1";
38
38
 
39
39
  // ── State ──────────────────────────────────────────────────────────────────
40
40
 
@@ -0,0 +1,82 @@
1
+ // m4l_device/livepilot_elektron_bridge.js
2
+ // LivePilot Elektron Bridge — runs inside LivePilot_Elektron.amxd.
3
+ //
4
+ // Wire model:
5
+ //
6
+ // M4L → Python : UDP 9882
7
+ // Inbound SysEx from physical MIDI [sysexin → sxformat
8
+ // → prepend sysex] arrives at JS as a "sysex <bytes...>"
9
+ // message; forwards out outlet 1 (→ [udpsend 9882]).
10
+ //
11
+ // Python → M4L : UDP 9883
12
+ // [udpreceive 9883] outputs bytes as a "list" message
13
+ // → JS function list() pushes onto sendQueue.
14
+ // [metro 50 @active 1] drives bang() which drains one
15
+ // chunk per tick onto outlet 0 (→ [midiout]).
16
+ //
17
+ // Outlets:
18
+ // 0 → [midiout] paced chunks to physical MIDI port
19
+ // 1 → [udpsend 127.0.0.1 9882] sysex-from-device upstream to Python
20
+ // 2 → "set <text>" → live.text status display
21
+ // 3 → +1 counter → live.numbox RX message counter
22
+ //
23
+ // Phase 1 design note: heartbeat is intentionally OUT for v1 of the M4L
24
+ // device. The Python bridge uses per-operation timeouts (per design
25
+ // spec §7.3) so it does not need M4L liveness polling. Heartbeat / pong
26
+ // can be added in a Phase 2 patch to the .maxpat if "is M4L loaded?"
27
+ // detection becomes useful — the ping()/pong() functions below are
28
+ // kept as reserved stubs for that future wiring.
29
+
30
+ inlets = 1;
31
+ outlets = 4;
32
+
33
+ var sendQueue = [];
34
+ var rxCount = 0;
35
+
36
+ // Called by [metro 50 @active 1] — drain one queued chunk per tick.
37
+ function bang() {
38
+ if (sendQueue.length > 0) {
39
+ var chunk = sendQueue.shift();
40
+ // Spread chunk into outlet args so Max sees it as a list message
41
+ outlet.apply(this, [0].concat(chunk));
42
+ }
43
+ }
44
+
45
+ // Called by [udpreceive 9883] — outputs raw UDP bytes as a list.
46
+ // This is the Python → M4L outbound MIDI path. Each datagram is a
47
+ // pre-chunked SysEx fragment; we queue and let bang() pace them.
48
+ function list() {
49
+ var bytes = [];
50
+ for (var i = 0; i < arguments.length; i++) {
51
+ bytes.push(arguments[i]);
52
+ }
53
+ sendQueue.push(bytes);
54
+ }
55
+
56
+ // Called when [sysexin → sxformat → prepend sysex] delivers a complete
57
+ // SysEx as a "sysex <bytes...>" message. We forward to Python and
58
+ // bump the RX counter + status.
59
+ function sysex() {
60
+ var bytes = [];
61
+ for (var i = 0; i < arguments.length; i++) {
62
+ bytes.push(arguments[i]);
63
+ }
64
+ // Forward to Python via outlet 1 → [udpsend 9882]
65
+ outlet.apply(this, [1].concat(bytes));
66
+ // Bump RX counter via outlet 3
67
+ rxCount += 1;
68
+ outlet(3, rxCount);
69
+ // Update status via outlet 2
70
+ outlet(2, "set", "Online — receiving SysEx");
71
+ }
72
+
73
+ // Phase 2 reserved: heartbeat ping. Wire [metro 1000] → [t ping] → js
74
+ // to enable. Not wired in Phase 1 .maxpat.
75
+ function ping() {
76
+ outlet(1, 0xF0, 0x7F, 0x7F, 0x00, 0xF7);
77
+ }
78
+
79
+ // Phase 2 reserved: receive pong from Python. Currently unused.
80
+ function pong() {
81
+ outlet(2, "set", "Online — pong received");
82
+ }
@@ -1,2 +1,2 @@
1
1
  """LivePilot MCP Server — bridges MCP protocol to Ableton Live."""
2
- __version__ = "1.26.0"
2
+ __version__ = "1.26.1"
@@ -64,7 +64,7 @@ async def _bridge_ping_stub(ctx: Any) -> dict:
64
64
  bridge = ctx.lifespan_context.get("m4l_bridge")
65
65
  if bridge is None:
66
66
  raise RuntimeError("bridge not available")
67
- return await bridge.send_command("ping", {"timeout": 0.5})
67
+ return await bridge.send_command("ping", timeout=0.5)
68
68
 
69
69
 
70
70
  async def _back_to_arranger(ctx: Any) -> dict:
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
  import re as _re
7
+ import inspect
7
8
  import time
8
9
 
9
10
  from fastmcp import Context
@@ -92,6 +93,28 @@ _TONAL_ROLES_ALWAYS_WARP: frozenset[str] = frozenset({
92
93
  })
93
94
 
94
95
 
96
+ async def _call_mcp_analysis_tool(ctx: Context, tool: str, params: dict) -> dict:
97
+ """Dispatch analyzer/intelligence tools through the MCP registry.
98
+
99
+ These tools are Python MCP tools, not Remote Script TCP handlers. Keeping
100
+ full-mode analysis on the registry path prevents creative plans from
101
+ passing tests against mocks and then failing in Live as unknown commands.
102
+ """
103
+ lifespan = getattr(ctx, "lifespan_context", {}) or {}
104
+ registry = lifespan.get("mcp_dispatch")
105
+ if registry is None:
106
+ from ...runtime.mcp_dispatch import build_mcp_dispatch_registry
107
+ registry = build_mcp_dispatch_registry()
108
+
109
+ fn = registry.get(tool) if registry else None
110
+ if fn is None:
111
+ return {"error": f"MCP analysis tool '{tool}' is not registered"}
112
+
113
+ call = fn(params, ctx=ctx)
114
+ result = await call if inspect.isawaitable(call) else call
115
+ return result if isinstance(result, dict) else {"result": result}
116
+
117
+
95
118
  def _decide_warp_loops(
96
119
  role: str,
97
120
  file_path: str,
@@ -825,8 +848,9 @@ async def apply_full_plan_v2(ctx: Context, plan: dict) -> dict:
825
848
  # Goal: give the agent acoustic characteristics of the loaded sound so
826
849
  # it can reason about fit. ONLY static analysis here (no playback);
827
850
  # active solo-trigger analysis is Scope B / v1.25.
828
- # Analysis is routed through ableton.send_command so it is intercepted
829
- # by the same mock contract as all other commands (testable, consistent).
851
+ # Analysis is MCP-side intelligence, not a Remote Script TCP command.
852
+ # Route through the MCP dispatch registry so live execution matches
853
+ # the same boundary the async plan router uses.
830
854
  role = track_spec.get("role", "")
831
855
  instrument_uri = (track_spec.get("instrument") or {}).get("uri", "")
832
856
  layer_analysis: dict = {"status": "skipped", "reason": "no analyzer applicable"}
@@ -834,7 +858,8 @@ async def apply_full_plan_v2(ctx: Context, plan: dict) -> dict:
834
858
  if instrument_uri.startswith(("query:Synths#", "query:Sounds#")):
835
859
  # Synth / preset — analyze the patch
836
860
  try:
837
- patch_result = ableton.send_command(
861
+ patch_result = await _call_mcp_analysis_tool(
862
+ ctx,
838
863
  "analyze_synth_patch",
839
864
  {"track_index": track_index, "device_index": 0},
840
865
  )
@@ -854,7 +879,8 @@ async def apply_full_plan_v2(ctx: Context, plan: dict) -> dict:
854
879
  any(instrument_uri.lower().endswith(ext) for ext in (".aif", ".wav", ".mp3", ".flac")):
855
880
  # Sample-based — analyze via track reference (no file_path needed)
856
881
  try:
857
- sample_result = ableton.send_command(
882
+ sample_result = await _call_mcp_analysis_tool(
883
+ ctx,
858
884
  "analyze_sample",
859
885
  {"track_index": track_index, "clip_index": 0},
860
886
  )
@@ -1034,10 +1060,10 @@ async def apply_full_plan_v2(ctx: Context, plan: dict) -> dict:
1034
1060
  # session state.
1035
1061
  mix_analysis: dict = {"status": "skipped", "reason": "not run"}
1036
1062
  try:
1037
- mix_result = ableton.send_command("analyze_mix", {})
1063
+ mix_result = await _call_mcp_analysis_tool(ctx, "analyze_mix", {})
1038
1064
  if isinstance(mix_result, dict) and not mix_result.get("error"):
1039
1065
  try:
1040
- masking_result = ableton.send_command("get_masking_report", {})
1066
+ masking_result = await _call_mcp_analysis_tool(ctx, "get_masking_report", {})
1041
1067
  except Exception as mask_exc:
1042
1068
  masking_result = {"error": str(mask_exc)}
1043
1069
  mix_analysis = {
@@ -1014,6 +1014,11 @@ class M4LBridge:
1014
1014
  while len(s_bytes) % 4 != 0:
1015
1015
  s_bytes += b'\x00'
1016
1016
  arg_data += s_bytes
1017
+ else:
1018
+ raise TypeError(
1019
+ "OSC argument for %s must be int, float, or str, got %s"
1020
+ % (address, type(arg).__name__)
1021
+ )
1017
1022
 
1018
1023
  tag_bytes = type_tags.encode('ascii') + b'\x00'
1019
1024
  while len(tag_bytes) % 4 != 0:
@@ -36,7 +36,10 @@ from .remote_commands import BRIDGE_COMMANDS, REMOTE_COMMANDS
36
36
  MCP_TOOLS: frozenset[str] = frozenset({
37
37
  "apply_automation_shape",
38
38
  "apply_gesture_template",
39
+ "analyze_sample",
40
+ "analyze_synth_patch",
39
41
  "analyze_mix",
42
+ "get_masking_report",
40
43
  "get_master_spectrum",
41
44
  "get_emotional_arc",
42
45
  "get_motif_graph",
@@ -92,7 +95,10 @@ READ_ONLY_TOOLS: frozenset[str] = frozenset({
92
95
  "get_cue_points",
93
96
  "get_rack_chains",
94
97
  "get_clip_automation",
98
+ "analyze_sample",
99
+ "analyze_synth_patch",
95
100
  "analyze_mix",
101
+ "get_masking_report",
96
102
  "get_emotional_arc",
97
103
  "get_motif_graph",
98
104
  "get_session_diagnostics",
@@ -60,11 +60,26 @@ async def _apply_gesture_template(params: dict, ctx: Any = None) -> dict:
60
60
  return await _call(apply_gesture_template, ctx, params)
61
61
 
62
62
 
63
+ async def _analyze_sample(params: dict, ctx: Any = None) -> dict:
64
+ from ..sample_engine.tools import analyze_sample
65
+ return await _call(analyze_sample, ctx, params)
66
+
67
+
68
+ async def _analyze_synth_patch(params: dict, ctx: Any = None) -> dict:
69
+ from ..synthesis_brain.tools import analyze_synth_patch
70
+ return await _call(analyze_synth_patch, ctx, params)
71
+
72
+
63
73
  async def _analyze_mix(params: dict, ctx: Any = None) -> dict:
64
74
  from ..mix_engine.tools import analyze_mix
65
75
  return await _call(analyze_mix, ctx, params)
66
76
 
67
77
 
78
+ async def _get_masking_report(params: dict, ctx: Any = None) -> dict:
79
+ from ..mix_engine.tools import get_masking_report
80
+ return await _call(get_masking_report, ctx, params)
81
+
82
+
68
83
  async def _get_master_spectrum(params: dict, ctx: Any = None) -> dict:
69
84
  from ..tools.analyzer import get_master_spectrum
70
85
  return await _call(get_master_spectrum, ctx, params)
@@ -151,7 +166,10 @@ def build_mcp_dispatch_registry() -> dict[str, Callable]:
151
166
  "load_sample_to_simpler": _load_sample_to_simpler,
152
167
  "apply_automation_shape": _apply_automation_shape,
153
168
  "apply_gesture_template": _apply_gesture_template,
169
+ "analyze_sample": _analyze_sample,
170
+ "analyze_synth_patch": _analyze_synth_patch,
154
171
  "analyze_mix": _analyze_mix,
172
+ "get_masking_report": _get_masking_report,
155
173
  "get_master_spectrum": _get_master_spectrum,
156
174
  "get_emotional_arc": _get_emotional_arc,
157
175
  "get_motif_graph": _get_motif_graph,
@@ -83,6 +83,8 @@ REMOTE_COMMANDS: frozenset[str] = frozenset({
83
83
  "capture_midi", "start_recording", "stop_recording",
84
84
  "get_cue_points", "jump_to_cue", "toggle_cue_point",
85
85
  "back_to_arranger", "force_arrangement",
86
+ "arrangement_automation_via_session_record_start",
87
+ "arrangement_automation_via_session_record_complete",
86
88
  # scales — Song + per-clip scale awareness (Live 12.0+)
87
89
  "get_song_scale", "set_song_scale", "set_song_scale_mode",
88
90
  "list_available_scales",
@@ -355,14 +355,14 @@ def _coerce_schema_property(prop: dict) -> None:
355
355
  def _get_all_tools():
356
356
  """Get all registered tools — defends against FastMCP internal drift.
357
357
 
358
- FastMCP's public API doesn't expose the registry as of 3.2.x (see
358
+ FastMCP's public API doesn't expose the registry as of 3.3.x (see
359
359
  docs/FASTMCP_UPSTREAM_FR.md). Until it does, we probe known internal
360
360
  attribute paths. Each probe fires in try/except so a structural
361
- rearrangement (e.g. ``_components`` renamed under 3.3+) falls through
361
+ rearrangement (e.g. ``_components`` renamed under 3.4+) falls through
362
362
  to the next path rather than exploding.
363
363
 
364
364
  WARNING: Accesses FastMCP private internals. Pinned to
365
- fastmcp>=3.0.0,<3.3.0 in requirements.txt. The startup self-test
365
+ fastmcp>=3.3.1,<3.4.0 in requirements.txt. The startup self-test
366
366
  (_assert_tool_registry_accessible) will fail loudly if every probe
367
367
  returns empty — better than silently returning [] and disabling
368
368
  schema coercion.
@@ -370,14 +370,18 @@ def _get_all_tools():
370
370
  probes = [
371
371
  # FastMCP 0.x: mcp._tool_manager._tools (dict of name -> Tool)
372
372
  ("_tool_manager._tools", lambda: list(mcp._tool_manager._tools.values())),
373
- # FastMCP 3.0–3.2: mcp._local_provider._components
373
+ # FastMCP 3.0–3.3: mcp._local_provider._components
374
+ # (verified 2026-05-21 against fastmcp 3.3.1 — still the active path)
374
375
  (
375
376
  "_local_provider._components",
376
377
  lambda: list(mcp._local_provider._components.values()),
377
378
  ),
378
- # FastMCP 3.3+ speculative: mcp._local_provider._tools (anticipated
379
- # rename based on naming conventions in other providers). Kept here
380
- # so a future bump surfaces a partial match rather than a full miss.
379
+ # FastMCP 3.4+ speculative: mcp._local_provider._tools (anticipated
380
+ # rename based on naming conventions in other providers). Verified
381
+ # 2026-05-21 against fastmcp 3.3.1 the rename did NOT happen in
382
+ # 3.3.x; ``_local_provider._components`` remains the live registry.
383
+ # Kept here so a future bump that DOES rename surfaces a partial
384
+ # match rather than a full miss.
381
385
  (
382
386
  "_local_provider._tools",
383
387
  lambda: list(mcp._local_provider._tools.values()),
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "livepilot",
3
- "version": "1.26.0",
3
+ "version": "1.26.1",
4
4
  "mcpName": "io.github.dreamrec/livepilot",
5
- "description": "Agentic production system for Ableton Live 12 \u2014 465 tools, 56 domains, 44 semantic moves. Device atlas (5264 devices, 120 enriched, 7 indexes), Splice intelligence (gRPC + GraphQL describe-a-sound + preview + collections + presets), 9-band spectral perception auto-loaded via ensure_analyzer_on_master, Creative Director skill, technique memory, 12 creative intelligence engines",
5
+ "description": "Agentic production system for Ableton Live 12 465 tools, 56 domains, 44 semantic moves. Device atlas (5264 devices, 120 enriched, 7 indexes), Splice intelligence (gRPC + GraphQL describe-a-sound + preview + collections + presets), 9-band spectral perception auto-loaded via ensure_analyzer_on_master, Creative Director skill, technique memory, 12 creative intelligence engines",
6
6
  "author": "Pilot Studio",
7
7
  "license": "BSL-1.1",
8
8
  "type": "commonjs",
9
9
  "bin": {
10
- "livepilot": "./bin/livepilot.js"
10
+ "livepilot": "bin/livepilot.js"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "https://github.com/dreamrec/LivePilot"
14
+ "url": "git+https://github.com/dreamrec/LivePilot.git"
15
15
  },
16
16
  "homepage": "https://github.com/dreamrec/LivePilot",
17
17
  "bugs": {
@@ -47,6 +47,7 @@
47
47
  "files": [
48
48
  "bin/**/*.js",
49
49
  "installer/**/*.js",
50
+ "livepilot/**",
50
51
  "mcp_server/**/*.py",
51
52
  "mcp_server/**/*.json",
52
53
  "mcp_server/**/*.yaml",
@@ -56,6 +57,9 @@
56
57
  "m4l_device/LivePilot_Analyzer.amxd",
57
58
  "m4l_device/LivePilot_Analyzer.adv",
58
59
  "m4l_device/livepilot_bridge.js",
60
+ "m4l_device/LivePilot_Elektron.amxd",
61
+ "m4l_device/LivePilot_Elektron.maxpat",
62
+ "m4l_device/livepilot_elektron_bridge.js",
59
63
  "m4l_device/BUILD_GUIDE.md",
60
64
  "requirements.txt",
61
65
  "README.md",
@@ -64,6 +68,17 @@
64
68
  "server.json",
65
69
  "!**/__pycache__/**",
66
70
  "!**/*.pyc",
67
- "!**/.DS_Store"
71
+ "!**/.DS_Store",
72
+ "!livepilot/skills/livepilot-core/references/device-atlas/synths-m4l.md",
73
+ "!livepilot/skills/livepilot-core/references/device-atlas/plugins-synths.md",
74
+ "!livepilot/skills/livepilot-core/references/device-atlas/utility-and-workflow.md",
75
+ "!livepilot/skills/livepilot-core/references/device-atlas/samples-and-irs.md",
76
+ "!livepilot/skills/livepilot-core/references/device-atlas/presets-by-vibe.md",
77
+ "!livepilot/skills/livepilot-devices/references/m4l-vendor/**",
78
+ "!livepilot/skills/livepilot-devices/references/m4l-depth-pass-findings.md",
79
+ "!livepilot/skills/livepilot-devices/references/m4l-depth-pass-resume.md",
80
+ "!livepilot/skills/livepilot-devices/references/m4l-library-deep.md",
81
+ "!livepilot/skills/livepilot-devices/references/m4l-master-reference.md",
82
+ "!livepilot/skills/livepilot-devices/references/m4l-technique-map.md"
68
83
  ]
69
84
  }
@@ -5,7 +5,7 @@ Entry point for the ControlSurface. Ableton calls create_instance(c_instance)
5
5
  when this script is selected in Preferences > Link, Tempo & MIDI.
6
6
  """
7
7
 
8
- __version__ = "1.26.0"
8
+ __version__ = "1.26.1"
9
9
 
10
10
  from _Framework.ControlSurface import ControlSurface
11
11
  from . import router
@@ -60,6 +60,67 @@ WRITE_COMMANDS = frozenset([
60
60
  "clear_clip_automation",
61
61
  ])
62
62
 
63
+ # Future-safe write detection. WRITE_COMMANDS remains the explicit allow-list
64
+ # for older handlers and readability; the prefix classifier catches newer
65
+ # mutating handlers so they still receive the write timeout and settle delay.
66
+ READ_COMMAND_PREFIXES = ("get_", "list_", "scan_")
67
+ READ_ONLY_COMMANDS = frozenset([
68
+ "ping",
69
+ "reload_handlers",
70
+ ])
71
+ WRITE_COMMAND_PREFIXES = (
72
+ "add_",
73
+ "apply_",
74
+ "arrangement_automation_",
75
+ "assign_",
76
+ "back_to_",
77
+ "capture_",
78
+ "cleanup_",
79
+ "clear_",
80
+ "continue_",
81
+ "copy_",
82
+ "create_",
83
+ "delete_",
84
+ "duplicate_",
85
+ "find_and_load_",
86
+ "fire_",
87
+ "flatten_",
88
+ "force_",
89
+ "freeze_",
90
+ "import_",
91
+ "insert_",
92
+ "jump_",
93
+ "load_",
94
+ "modify_",
95
+ "move_",
96
+ "nudge_",
97
+ "quantize_",
98
+ "randomize_",
99
+ "recall_",
100
+ "remove_",
101
+ "replace_",
102
+ "reset_",
103
+ "set_",
104
+ "start_",
105
+ "stop_",
106
+ "store_",
107
+ "tap_",
108
+ "toggle_",
109
+ "transpose_",
110
+ )
111
+
112
+
113
+ def is_write_command(command_type):
114
+ """Return True if a command is expected to mutate Live state."""
115
+ if command_type in WRITE_COMMANDS:
116
+ return True
117
+ if command_type in READ_ONLY_COMMANDS:
118
+ return False
119
+ if command_type.startswith(READ_COMMAND_PREFIXES):
120
+ return False
121
+ return command_type.startswith(WRITE_COMMAND_PREFIXES)
122
+
123
+
63
124
  # Commands that need longer timeouts (e.g., freeze renders audio)
64
125
  SLOW_WRITE_COMMANDS = frozenset([
65
126
  "freeze_track",
@@ -277,7 +338,7 @@ class LivePilotServer(object):
277
338
  cmd_type = command.get("type", "")
278
339
 
279
340
  # Determine timeout based on read vs write vs slow write
280
- is_write = cmd_type in WRITE_COMMANDS
341
+ is_write = is_write_command(cmd_type)
281
342
  if cmd_type in SLOW_WRITE_COMMANDS:
282
343
  timeout = 35
283
344
  elif is_write:
@@ -343,7 +404,7 @@ class LivePilotServer(object):
343
404
  return
344
405
 
345
406
  cmd_type = command.get("type", "")
346
- is_write = cmd_type in WRITE_COMMANDS
407
+ is_write = is_write_command(cmd_type)
347
408
 
348
409
  try:
349
410
  song = self._cs.song()
package/requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # LivePilot MCP Server dependencies
2
- numpy>=2.4.4
3
- fastmcp>=3.2.4,<3.3.0 # pinned upper bound — _get_all_tools() accesses private internals
2
+ numpy>=2.4.6
3
+ fastmcp>=3.3.1,<3.4.0 # pinned upper bound — _get_all_tools() accesses private internals
4
4
  midiutil>=1.2.1
5
5
  pretty_midi>=0.2.11
6
6
  # v1.8 Perception Layer (offline analysis)
@@ -13,7 +13,7 @@ mutagen>=1.47.0
13
13
  # falls back to the SQLite sounds.db which only returns locally downloaded
14
14
  # samples (see docs/2026-04-14-bugs-discovered.md — P0-2).
15
15
  grpcio>=1.80.0
16
- protobuf>=7.34.1
16
+ protobuf>=7.35.0
17
17
 
18
18
  # Known benign warning during install:
19
19
  # ERROR: pip's dependency resolver does not currently take into account
package/server.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.dreamrec/livepilot",
4
- "description": "465-tool agentic MCP production system for Ableton Live 12 \u2014 55 domains, 44 semantic moves, device atlas (5264 devices), Splice intelligence (gRPC + GraphQL), 9-band spectral perception auto-loaded, Creative Director skill, technique memory, 12 creative engines",
4
+ "description": "465-tool agentic MCP production system for Ableton Live 12 \u2014 56 domains, 44 semantic moves, device atlas (5264 devices), Splice intelligence (gRPC + GraphQL), 9-band spectral perception auto-loaded, Creative Director skill, technique memory, 12 creative engines",
5
5
  "repository": {
6
6
  "url": "https://github.com/dreamrec/LivePilot",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.26.0",
9
+ "version": "1.26.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "livepilot",
14
- "version": "1.26.0",
14
+ "version": "1.26.1",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  }