@williamzujkowski/live-coding-music-mcp 2.0.0 → 3.0.0

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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  >
5
5
  > **Unofficial fan project.** Not affiliated with, or endorsed by, the [Strudel project](https://codeberg.org/uzu/strudel). This adapter exists to make live-coding music accessible to beginners who want to try pattern-based music without learning the whole ecosystem first.
6
6
  >
7
- > **Status:** Beta | 77% test coverage | Published to npm | Actively developed
7
+ > **Status:** Beta | 86% statement coverage | Published to npm | Actively developed
8
8
 
9
9
  <a href="https://glama.ai/mcp/servers/@williamzujkowski/live-coding-music-mcp">
10
10
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@williamzujkowski/live-coding-music-mcp/badge" alt="live-coding-music-mcp server" />
@@ -13,16 +13,16 @@
13
13
  [![CI](https://github.com/williamzujkowski/live-coding-music-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/williamzujkowski/live-coding-music-mcp/actions)
14
14
  [![npm version](https://img.shields.io/npm/v/@williamzujkowski/live-coding-music-mcp.svg)](https://www.npmjs.com/package/@williamzujkowski/live-coding-music-mcp)
15
15
  [![Nerq Trust](https://nerq.ai/badge/live-coding-music-mcp)](https://nerq.ai/kya/live-coding-music-mcp)
16
- [![Tools](https://img.shields.io/badge/tools-66-green.svg)]()
16
+ [![Tools](https://img.shields.io/badge/tools-84-green.svg)]()
17
17
  [![License](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue.svg)](LICENSE)
18
18
 
19
19
  A Model Context Protocol (MCP) server that drives [Strudel.cc](https://strudel.cc/) from Claude for AI-assisted live-coding music, pattern generation, and algorithmic composition.
20
20
 
21
- **Current State: Beta.** The core workflow (init → generate → write → play → analyze) works reliably with real audio output and has 1470 passing tests covering 77% of statements. CI is hardened with OpenSSF Scorecard, SHA-pinned actions, CODEOWNERS, and Dependabot. Known coverage gaps exist (notably `AudioCaptureService` at 33% and `AudioAnalyzer` branch coverage at 48%) — see [open issues](https://github.com/williamzujkowski/live-coding-music-mcp/issues) for the full list.
21
+ **Current State: Beta.** The core workflow (init → generate → write → play → analyze) works reliably with real audio output. 1771 tests pass, 86.76% statement coverage / 77.32% branch coverage. CI is hardened with OpenSSF Scorecard, SHA-pinned actions, CODEOWNERS, Dependabot, and lint as a blocking gate.
22
22
 
23
23
  **What "Beta" means here:**
24
24
  - Tool schemas are stable within minor versions; breaking changes require a major bump
25
- - Single-browser-session limitation (multi-session tracked in [#108](https://github.com/williamzujkowski/live-coding-music-mcp/issues/108))
25
+ - Multi-session is supported as of v3.0.0 ([#108](https://github.com/williamzujkowski/live-coding-music-mcp/issues/108)) — named sessions get isolated browser, history, and audio-capture state
26
26
  - Upstream `@strudel/*` dependencies pinned to known-good versions; Dependabot bumps gated on CI
27
27
  - Expect hands-on iteration for non-standard patterns — report rough edges, they get fixed
28
28
 
@@ -44,40 +44,39 @@ A Model Context Protocol (MCP) server that drives [Strudel.cc](https://strudel.c
44
44
 
45
45
  ## Features
46
46
 
47
- ### 🎹 Complete Music Control
48
- - **65 MCP Tools**: Comprehensive suite for music creation and manipulation
49
- - **Real Browser Automation**: Direct control of Strudel.cc through Playwright
50
- - **Live Audio Analysis**: Real-time frequency analysis via Web Audio API
51
- - **Pattern Generation**: AI-powered creation across 8+ music genres
52
- - **Music Theory Engine**: Scales, chords, progressions, euclidean rhythms
53
- - **Session Management**: Save, load, undo/redo with pattern storage
54
-
55
- ### 🔧 Testing & Development Status
56
- - ✅ **Test Suite**: Comprehensive test coverage across unit, integration, and validation tests
57
- - ✅ **Code Coverage**: Actively tracked via CI
58
- - ✅ **Browser Integration**: Works with live Strudel.cc website
59
- - ✅ **Audio Analysis**: Real-time FFT analysis functional
60
- - ✅ **Pattern Generation**: Core music generation features working
61
- - ✅ **OIDC Publishing**: Secure npm publishing with provenance attestation
47
+ ### 🎹 Music control
48
+ - **84 MCP tools** covering pattern editing, playback, audio analysis, generation, history, sessions, and Gemini-backed assists. 26 are the canonical consolidated tools (`pattern_store`, `edit_pattern`, `transform`, `analyze`, `history`, `playback`, `effect`, `shape`, `audio_capture`, `browser_window`, `generate_part`, `generate_rhythm`, `music_theory`, `session`, `ai_assist`, ...); the rest are deprecated aliases kept for one release ([#178](https://github.com/williamzujkowski/live-coding-music-mcp/issues/178)).
49
+ - **4 MCP resources** for catalog browsing without burning tool calls: `strudel://examples`, `strudel://patterns`, `strudel://styles`, `strudel://docs/tools`.
50
+ - **Real browser automation** of Strudel.cc through Playwright.
51
+ - **Multi-session support** — every browser-touching tool accepts an optional `session_id`; sessions have isolated browser pages, undo/redo/history stacks, and audio-capture services.
52
+ - **Audio analysis** via Web Audio API (FFT spectrum, tempo detection, key detection, rhythm complexity).
53
+ - **Template-based pattern generation** across 8 genres (techno, house, dnb, ambient, trap, jungle, jazz, experimental); optional Gemini-backed `ai_assist` for feedback, suggestions, and jamming.
54
+ - **Music theory helpers**: 15+ scales, 8+ chord progression styles, euclidean and polyrhythm generation.
55
+ - **Pattern persistence**: JSON-backed save/load with tags + the in-memory edit history (undo/redo/restore/compare).
56
+ - **Result envelope** on every `tools/call`: clients branch on `{ ok, errorCategory, isRetryable }` instead of parsing free-text.
57
+
58
+ ### 🔧 Testing & CI status
59
+ - **1771 passing tests** across unit, integration, and example-validation suites.
60
+ - **86.76% statement coverage / 77.32% branch coverage**.
61
+ - **Lint blocking in CI**: 0 errors, ~163 warnings (mostly `any` in test mocks).
62
+ - **OIDC trusted publishing** to npm with SLSA build provenance attestation on every release.
62
63
 
63
64
  **Not Production-Ready:** This is experimental software under active development. Use for exploration and experimentation. Expect breaking changes, bugs, and incomplete features. See [CONTRIBUTING.md](CONTRIBUTING.md) to help improve it.
64
65
 
65
- ### 🎼 Example Patterns
66
+ ### 🎼 Example patterns
66
67
 
67
- Explore 17 curated example patterns across 10 genres in [`patterns/examples/`](patterns/examples/):
68
+ 18 example patterns ship in [`patterns/examples/`](patterns/examples/), grouped by genre:
68
69
 
69
- - **Techno**: Hard techno, minimal techno
70
- - **House**: Deep house, tech house
71
- - **Drum & Bass**: Liquid, neurofunk
72
- - **Ambient**: Dark ambient, drone
73
- - **Trap**: Modern trap, cloud trap
74
- - **Jungle**: Classic jungle, ragga jungle
75
- - **Jazz**: Bebop, modal jazz
76
- - **Intelligent DnB**: Atmospheric, liquid, LTJ Bukem style
77
- - **Trip Hop**: Portishead, Massive Attack, Flying Lotus style
78
- - **Boom Bap**: DJ Premier, Alchemist, golden era hip hop
70
+ - **Techno**: hard-techno, minimal-techno
71
+ - **House**: deep-house, tech-house
72
+ - **Drum & Bass**: liquid-dnb, neurofunk
73
+ - **Ambient**: dark-ambient, drone
74
+ - **Trap**: modern-trap, cloud-trap
75
+ - **Jungle**: classic-jungle, ragga-jungle
76
+ - **Jazz**: bebop, modal-jazz
77
+ - **Longform** (multi-minute pieces): dark-ambient-journey, driving-techno, liquid-dnb-roller, nu-jazz-session
79
78
 
80
- Each example includes pattern code, BPM, key, and description. See [`patterns/examples/README.md`](patterns/examples/README.md) for details.
79
+ Each example is a JSON file with pattern code, BPM, key, and a description. See [`patterns/examples/README.md`](patterns/examples/README.md) for details. Agents can also list these via the `strudel://examples` MCP resource without making any tool calls.
81
80
 
82
81
  ## Migrating from `@williamzujkowski/strudel-mcp-server`
83
82
 
@@ -156,16 +155,21 @@ npm run build
156
155
 
157
156
  Common commands for immediate use:
158
157
 
159
- | Action | Command |
160
- |--------|---------|
158
+ | Action | Tool call |
159
+ |---|---|
161
160
  | Initialize browser | `init` |
162
- | Create techno beat | `generate_pattern` with `style: "techno"` |
163
- | Play pattern | `play` |
164
- | Stop playback | `stop` |
161
+ | Create a techno beat in one shot | `compose({ style: "techno" })` |
162
+ | Play pattern | `playback({ action: "play" })` |
163
+ | Stop playback | `playback({ action: "stop" })` |
165
164
  | Get current pattern | `get_pattern` |
166
- | Analyze audio | `analyze` |
167
- | Save pattern | `save` with `name: "my-pattern"` |
168
- | Undo last change | `undo` |
165
+ | Analyze audio (all features) | `analyze({ include: ["all"] })` |
166
+ | Detect tempo only | `analyze({ include: ["tempo"] })` |
167
+ | Save pattern | `pattern_store({ action: "save", name: "my-pattern" })` |
168
+ | Undo last edit | `history({ action: "undo" })` |
169
+ | Edit current pattern | `edit_pattern({ mode: "write", pattern: "..." })` |
170
+ | Create an isolated session | `session({ action: "create", session_id: "live-1" })` |
171
+
172
+ The legacy single-verb tools (`play`, `stop`, `save`, `undo`, `write`, `generate_pattern`, ...) still work in v3.0 as deprecated aliases. They forward to the consolidated tools and will be removed in v3.1 ([#178](https://github.com/williamzujkowski/live-coding-music-mcp/issues/178)).
169
173
 
170
174
  **One-shot workflow:**
171
175
  ```
@@ -197,7 +201,7 @@ Then ask Claude:
197
201
 
198
202
  <!-- TOOLS:START -->
199
203
 
200
- **66 tools** across 15 categories:
204
+ **84 tools** across 15 categories:
201
205
 
202
206
  <details><summary><strong>Setup</strong> (1)</summary>
203
207
 
@@ -211,11 +215,11 @@ Then ask Claude:
211
215
 
212
216
  | Tool | Description |
213
217
  |------|-------------|
214
- | `write` | Write pattern to editor with optional auto-play and validation |
215
- | `append` | Append code to current pattern |
216
- | `insert` | Insert code at specific line |
217
- | `replace` | Replace pattern section |
218
218
  | `get_pattern` | Get current pattern code |
219
+ | `write` | [DEPRECATED — use edit_pattern({ mode: "write" }) instead] Write pattern to editor with optional auto-play and validation |
220
+ | `append` | [DEPRECATED — use edit_pattern({ mode: "append" }) instead] Append code to current pattern |
221
+ | `insert` | [DEPRECATED — use edit_pattern({ mode: "insert" }) instead] Insert code at specific line |
222
+ | `replace` | [DEPRECATED — use edit_pattern({ mode: "replace" }) instead] Replace pattern section |
219
223
 
220
224
  </details>
221
225
 
@@ -223,11 +227,11 @@ Then ask Claude:
223
227
 
224
228
  | Tool | Description |
225
229
  |------|-------------|
226
- | `status` | Get current browser and playback status (quick state check) |
227
- | `clear` | Clear the editor |
228
- | `play` | Start playing pattern |
229
- | `pause` | Pause playback |
230
- | `stop` | Stop playback |
230
+ | `status` | [DEPRECATED — use diagnostics({ level: "status" }) instead] Get current browser and playback status (quick state check) |
231
+ | `clear` | [DEPRECATED — use edit_pattern({ mode: "clear" }) instead] Clear the editor |
232
+ | `play` | [DEPRECATED — use playback({ action: "play" }) instead] Start playing pattern |
233
+ | `pause` | [DEPRECATED — use playback({ action: "pause" }) instead] Pause playback |
234
+ | `stop` | [DEPRECATED — use playback({ action: "stop" }) instead] Stop playback |
231
235
  | `set_tempo` | Set BPM |
232
236
 
233
237
  </details>
@@ -236,9 +240,9 @@ Then ask Claude:
236
240
 
237
241
  | Tool | Description |
238
242
  |------|-------------|
239
- | `save` | Save pattern with metadata |
240
- | `load` | Load saved pattern |
241
- | `list` | List saved patterns |
243
+ | `save` | [DEPRECATED — use pattern_store({ action: "save" }) instead] Save pattern with metadata |
244
+ | `load` | [DEPRECATED — use pattern_store({ action: "load" }) instead] Load saved pattern |
245
+ | `list` | [DEPRECATED — use pattern_store({ action: "list" }) instead] List saved patterns |
242
246
 
243
247
  </details>
244
248
 
@@ -246,10 +250,10 @@ Then ask Claude:
246
250
 
247
251
  | Tool | Description |
248
252
  |------|-------------|
249
- | `undo` | Undo last action |
250
- | `redo` | Redo action |
251
- | `list_history` | List recent pattern history with timestamps and previews |
252
- | `restore_history` | Restore a previous pattern from history by ID |
253
+ | `undo` | [DEPRECATED — use history({ action: "undo" }) instead] Undo last action |
254
+ | `redo` | [DEPRECATED — use history({ action: "redo" }) instead] Redo action |
255
+ | `list_history` | [DEPRECATED — use history({ action: "list" }) instead] List recent pattern history with timestamps and previews |
256
+ | `restore_history` | [DEPRECATED — use history({ action: "restore" }) instead] Restore a previous pattern from history by ID |
253
257
 
254
258
  </details>
255
259
 
@@ -257,14 +261,14 @@ Then ask Claude:
257
261
 
258
262
  | Tool | Description |
259
263
  |------|-------------|
260
- | `compose` | Generate, write, and play a complete pattern in one step. Auto-initializes browser if needed. |
261
- | `generate_pattern` | Generate complete pattern from style with optional auto-play |
262
- | `generate_drums` | Generate drum pattern |
263
- | `generate_bassline` | Generate bassline |
264
- | `generate_melody` | Generate melody from scale |
265
- | `generate_polyrhythm` | Generate polyrhythm |
266
- | `generate_fill` | Generate drum fill |
267
- | `generate_variation` | Create pattern variations |
264
+ | `compose` | Generate, write, and play a complete pattern in one step. Auto-initializes default browser if needed. |
265
+ | `generate_pattern` | [DEPRECATED — use compose instead, which auto-inits and returns richer metadata] Generate complete pattern from style with optional auto-play. |
266
+ | `generate_drums` | [DEPRECATED — use generate_part({ role: "drums" }) instead] Generate drum pattern |
267
+ | `generate_bassline` | [DEPRECATED — use generate_part({ role: "bass" }) instead] Generate bassline |
268
+ | `generate_melody` | [DEPRECATED — use generate_part({ role: "melody" }) instead] Generate melody from scale |
269
+ | `generate_polyrhythm` | [DEPRECATED — use generate_rhythm({ type: "polyrhythm" }) instead] Generate polyrhythm |
270
+ | `generate_fill` | [DEPRECATED — use generate_part({ role: "fill" }) instead] Generate drum fill |
271
+ | `generate_variation` | [DEPRECATED — use transform({ op: "vary" }) instead] Create pattern variations (mis-named today; it transforms, not generates) |
268
272
 
269
273
  </details>
270
274
 
@@ -272,10 +276,10 @@ Then ask Claude:
272
276
 
273
277
  | Tool | Description |
274
278
  |------|-------------|
275
- | `generate_scale` | Generate scale notes |
276
- | `generate_chord_progression` | Generate chord progression |
277
- | `generate_euclidean` | Generate Euclidean rhythm |
278
- | `apply_scale` | Apply scale to notes |
279
+ | `generate_scale` | [DEPRECATED — use music_theory({ query: "scale" }) instead] Generate scale notes |
280
+ | `generate_chord_progression` | [DEPRECATED — use music_theory({ query: "chord_progression" }) instead] Generate chord progression |
281
+ | `generate_euclidean` | [DEPRECATED — use generate_rhythm({ type: "euclidean" }) instead] Generate Euclidean rhythm |
282
+ | `apply_scale` | [DEPRECATED — use transform({ op: "scale" }) instead] Apply scale to notes |
279
283
 
280
284
  </details>
281
285
 
@@ -283,15 +287,15 @@ Then ask Claude:
283
287
 
284
288
  | Tool | Description |
285
289
  |------|-------------|
286
- | `transpose` | Transpose notes by semitones |
287
- | `reverse` | Reverse pattern |
288
- | `stretch` | Time stretch pattern |
289
- | `quantize` | Quantize to grid |
290
- | `humanize` | Add human timing variation |
291
- | `add_effect` | Add effect to pattern |
292
- | `remove_effect` | Remove effect |
293
- | `add_swing` | Add swing to pattern |
294
- | `set_energy` | Adjust the overall energy level of the current pattern on a 0-10 scale. 0: minimal/ambient, 1-2: sparse, 3-4: light/relaxed, 5-6: normal/moderate, 7-8: driving/intense, 9-10: maximum. Auto-plays after applying energy level. |
290
+ | `transpose` | [DEPRECATED — use transform({ op: "transpose" }) instead] Transpose notes by semitones |
291
+ | `reverse` | [DEPRECATED — use transform({ op: "reverse" }) instead] Reverse pattern |
292
+ | `stretch` | [DEPRECATED — use transform({ op: "stretch" }) instead] Time stretch pattern |
293
+ | `quantize` | [DEPRECATED — use transform({ op: "quantize" }) instead] Quantize to grid |
294
+ | `humanize` | [DEPRECATED — use transform({ op: "humanize" }) instead] Add human timing variation |
295
+ | `add_effect` | [DEPRECATED — use effect({ action: "add" }) instead] Add effect to pattern |
296
+ | `remove_effect` | [DEPRECATED — use effect({ action: "remove" }) instead] Remove effect |
297
+ | `add_swing` | [DEPRECATED — use transform({ op: "swing" }) instead] Add swing to pattern |
298
+ | `set_energy` | [DEPRECATED — use shape({ dimension: "energy" }) instead] Adjust energy level 0-10. Auto-plays after applying. |
295
299
 
296
300
  </details>
297
301
 
@@ -299,10 +303,10 @@ Then ask Claude:
299
303
 
300
304
  | Tool | Description |
301
305
  |------|-------------|
302
- | `get_pattern_feedback` | Get AI-powered creative feedback on the current pattern using Google Gemini. Analyzes pattern structure and optionally audio. |
303
- | `jam_with` | AI generates a complementary layer to jam with your pattern. Analyzes current pattern to detect tempo, key, and existing layers, then generates a matching layer that fits musically. |
304
- | `shift_mood` | Transform current pattern to match a different emotional mood by adjusting tempo, effects, and note choices. Moods: dark, euphoric, melancholic, aggressive, dreamy, peaceful, energetic. |
305
- | `refine` | Incrementally refine the current pattern with simple directional commands. Supports: faster/slower (tempo), louder/quieter (gain), brighter/darker (filter cutoff), "more reverb"/drier (reverb). Auto-plays after applying refinement. |
306
+ | `get_pattern_feedback` | [DEPRECATED — use ai_assist({ task: "feedback" }) instead] Get AI-powered creative feedback on the current pattern using Google Gemini. |
307
+ | `jam_with` | [DEPRECATED — use ai_assist({ task: "jam" }) instead] AI generates a complementary layer to jam with your pattern. |
308
+ | `shift_mood` | [DEPRECATED — use shape({ dimension: "mood" }) instead] Transform current pattern to match a different emotional mood. Moods: dark, euphoric, melancholic, aggressive, dreamy, peaceful, energetic. |
309
+ | `refine` | [DEPRECATED — use shape({ dimension: "refine" }) instead] Incrementally refine current pattern: faster/slower/louder/quieter/brighter/darker/"more reverb"/drier. |
306
310
 
307
311
  </details>
308
312
 
@@ -310,13 +314,13 @@ Then ask Claude:
310
314
 
311
315
  | Tool | Description |
312
316
  |------|-------------|
313
- | `analyze` | Complete audio analysis |
314
- | `analyze_spectrum` | FFT spectrum analysis |
315
- | `analyze_rhythm` | Rhythm analysis |
316
- | `detect_tempo` | BPM detection |
317
- | `detect_key` | Key detection |
317
+ | `analyze` | Audio analysis on the currently-playing pattern. |
318
+ | `analyze_spectrum` | [DEPRECATED — use analyze({ include: ["spectrum"] }) instead] FFT spectrum analysis |
319
+ | `analyze_rhythm` | [DEPRECATED — use analyze({ include: ["rhythm"] }) instead] Rhythm analysis |
320
+ | `detect_tempo` | [DEPRECATED — use analyze({ include: ["tempo"] }) instead] BPM detection |
321
+ | `detect_key` | [DEPRECATED — use analyze({ include: ["key"] }) instead] Key detection |
318
322
  | `validate_pattern_runtime` | Validate pattern with runtime error checking (monitors Strudel console for errors) |
319
- | `compare_patterns` | Compare two patterns from history showing differences |
323
+ | `compare_patterns` | [DEPRECATED — use history({ action: "compare" }) instead] Compare two patterns from history showing differences |
320
324
 
321
325
  </details>
322
326
 
@@ -324,10 +328,10 @@ Then ask Claude:
324
328
 
325
329
  | Tool | Description |
326
330
  |------|-------------|
327
- | `create_session` | Create a new isolated Strudel browser session. Sessions share one browser but have isolated contexts. |
328
- | `destroy_session` | Close and destroy a Strudel session, releasing its resources. |
329
- | `list_sessions` | List all active Strudel sessions with their metadata. |
330
- | `switch_session` | Change the default session used by other tools. |
331
+ | `create_session` | [DEPRECATED — use session({ action: "create" }) instead] Create a new isolated Strudel browser session. |
332
+ | `destroy_session` | [DEPRECATED — use session({ action: "destroy" }) instead] Close and destroy a Strudel session. |
333
+ | `list_sessions` | [DEPRECATED — use session({ action: "list" }) instead] List all active Strudel sessions. |
334
+ | `switch_session` | [DEPRECATED — use session({ action: "switch" }) instead] Change the default session. |
331
335
 
332
336
  </details>
333
337
 
@@ -336,7 +340,7 @@ Then ask Claude:
336
340
  | Tool | Description |
337
341
  |------|-------------|
338
342
  | `export_midi` | Export current pattern to MIDI file. Parses note(), n(), and chord() functions. |
339
- | `screenshot` | Take a screenshot of the current Strudel editor state |
343
+ | `screenshot` | [DEPRECATED — use browser_window({ action: "screenshot" }) instead] Take a screenshot of the current Strudel editor state |
340
344
 
341
345
  </details>
342
346
 
@@ -344,9 +348,9 @@ Then ask Claude:
344
348
 
345
349
  | Tool | Description |
346
350
  |------|-------------|
347
- | `start_audio_capture` | Start capturing audio from Strudel output. Audio must be playing for capture to work. |
348
- | `stop_audio_capture` | Stop audio capture and return the recorded audio as base64-encoded data. |
349
- | `capture_audio_sample` | Capture a fixed-duration audio sample from Strudel output. Audio must be playing. |
351
+ | `start_audio_capture` | [DEPRECATED — use audio_capture({ action: "start" }) instead] Start capturing audio. Audio must be playing. |
352
+ | `stop_audio_capture` | [DEPRECATED — use audio_capture({ action: "stop" }) instead] Stop audio capture and return base64-encoded audio. |
353
+ | `capture_audio_sample` | [DEPRECATED — use audio_capture({ action: "sample" }) instead] Capture a fixed-duration audio sample. |
350
354
 
351
355
  </details>
352
356
 
@@ -354,23 +358,41 @@ Then ask Claude:
354
358
 
355
359
  | Tool | Description |
356
360
  |------|-------------|
357
- | `show_browser` | Bring browser window to foreground for visual feedback |
358
- | `performance_report` | Get performance metrics and bottlenecks |
359
- | `memory_usage` | Get current memory usage statistics |
360
- | `diagnostics` | Get detailed browser diagnostics including cache, errors, and performance |
361
- | `show_errors` | Display captured console errors and warnings from Strudel |
361
+ | `show_browser` | [DEPRECATED — use browser_window({ action: "show" }) instead] Bring browser window to foreground |
362
+ | `diagnostics` | Inspect server and browser state. |
363
+ | `show_errors` | [DEPRECATED — use diagnostics({ level: "errors" }) instead] Display captured console errors and warnings from Strudel |
364
+ | `performance_report` | [DEPRECATED — use diagnostics({ level: "perf" }) instead] Get performance metrics and bottlenecks |
365
+ | `memory_usage` | [DEPRECATED — use diagnostics({ level: "memory" }) instead] Get current memory usage statistics |
362
366
 
363
367
  </details>
364
368
 
365
- <details><summary><strong>Other</strong> (1)</summary>
369
+ <details><summary><strong>Other</strong> (19)</summary>
366
370
 
367
371
  | Tool | Description |
368
372
  |------|-------------|
369
- | `suggest_pattern_from_audio` | Analyze the currently playing audio and suggest a complementary Strudel pattern using Gemini AI. Extracts tempo, key, and spectral features locally, then uses AI to generate a matching pattern. Returns pattern text (not auto-executed). |
373
+ | `ai_assist` | Gemini-backed pattern assistance. |
374
+ | `suggest_pattern_from_audio` | [DEPRECATED — use ai_assist({ task: "suggest" }) instead] Analyze playing audio and suggest a complementary Strudel pattern. |
375
+ | `validate_pattern_local` | Validate pattern syntax against the in-process StrudelEngine (no browser required) |
376
+ | `analyze_pattern_local` | Static analysis (events/cycle, complexity, optional BPM) without browser playback |
377
+ | `query_pattern_events` | Enumerate events the pattern would emit between two cycle indices (max 16 cycles) |
378
+ | `transpile_pattern` | Transpile pattern source via StrudelEngine; returns transpiled code or syntax error |
379
+ | `audio_capture` | Record audio output from the live Strudel session. |
380
+ | `browser_window` | Interact with the visible Strudel browser window. |
381
+ | `edit_pattern` | Mutate the current session pattern. |
382
+ | `generate_part` | Generate a single instrumental layer and append it to the current session pattern. |
383
+ | `music_theory` | Music-theory queries. |
384
+ | `generate_rhythm` | Generate a rhythmic pattern and append it to the current session. |
385
+ | `history` | Navigate or inspect the pattern edit history. |
386
+ | `playback` | Control transport on the current session. |
387
+ | `session` | Manage isolated Strudel browser sessions (multi-session, #108). |
388
+ | `pattern_store` | Persist patterns to disk and read them back. |
389
+ | `transform` | Apply a single transform op to the current session pattern. |
390
+ | `effect` | Add or remove a Strudel effect on the current session pattern. |
391
+ | `shape` | Shape the current pattern along one of three high-level dimensions. |
370
392
 
371
393
  </details>
372
394
 
373
- _Auto-generated from source. 66 tools registered._
395
+ _Auto-generated from source. 84 tools registered._
374
396
 
375
397
  <!-- TOOLS:END -->
376
398
 
@@ -657,14 +679,15 @@ The Strudel MCP Server is built with a modular architecture that separates conce
657
679
 
658
680
  ### Core Components
659
681
 
660
- #### 1. **StrudelMCPServer** (`src/server/server.ts`)
682
+ #### 1. **StrudelMCPServer** (`src/server/server.ts`, ~510 lines)
661
683
 
662
- Main MCP server implementation handling:
663
- - **65 Tool Definitions**: Complete API surface for music control
664
- - **Request Routing**: Directs tool calls to appropriate handlers
665
- - **State Management**: Tracks initialization, undo/redo stacks, pattern cache
666
- - **Error Handling**: Graceful degradation and informative error messages
667
- - **Lazy Initialization**: Browser starts only when needed
684
+ Thin MCP dispatcher that:
685
+ - Aggregates 84 tool definitions from the per-domain modules in `src/server/tools/` (84 = 26 consolidated tools + 58 deprecated aliases; -58 once #178 lands)
686
+ - Routes `tools/call` requests to the right module's `execute()`
687
+ - Wraps every response in the discriminated result envelope (`{ ok, errorCategory, isRetryable, ... }`)
688
+ - Tracks initialization, per-session history bundles, per-session audio capture services
689
+ - Advertises and serves MCP resources (`strudel://examples`, etc.)
690
+ - Lazy-initializes the default browser controller on first browser-touching call
668
691
 
669
692
  Key Features:
670
693
  ```typescript
@@ -769,28 +792,42 @@ Persistent pattern storage:
769
792
  live-coding-music-mcp/
770
793
  ├── src/
771
794
  │ ├── server/
772
- │ │ └── server.ts # MCP server
795
+ │ │ ├── server.ts # MCP dispatcher (~510 lines)
796
+ │ │ ├── resources.ts # MCP resources (#131)
797
+ │ │ └── tools/
798
+ │ │ ├── ai.ts, analysis.ts, capture.ts, compose.ts,
799
+ │ │ ├── diagnostics.ts, editor.ts, generate.ts, history.ts,
800
+ │ │ ├── playback.ts, session.ts, storage.ts, transform.ts,
801
+ │ │ └── types.ts # ToolContext, Envelope, helpers
773
802
  │ ├── services/
774
- │ │ ├── MusicTheory.ts # Theory engine
775
- │ │ └── PatternGenerator.ts # Pattern creation
803
+ │ │ ├── MusicTheory.ts # Scale/chord/euclidean helpers
804
+ │ │ ├── PatternGenerator.ts # Template-based generation
805
+ │ │ ├── SessionManager.ts # Multi-session lifecycle (#108)
806
+ │ │ ├── AudioCaptureService.ts # Audio recording
807
+ │ │ ├── MIDIExportService.ts # MIDI export
808
+ │ │ ├── GeminiService.ts # Gemini API client (ai_assist)
809
+ │ │ ├── StrudelEngine.ts # @strudel/* wrapper
810
+ │ │ └── StrudelEngineHelpers.ts # Pure helpers (#107)
776
811
  │ ├── utils/
777
- │ │ └── Logger.ts # Logging utility
778
- │ ├── types/
779
- │ │ └── index.ts # TypeScript types
780
- │ ├── StrudelController.ts # Browser automation
781
- │ ├── AudioAnalyzer.ts # Audio analysis
782
- │ ├── PatternStore.ts # Pattern persistence
812
+ │ │ ├── Logger.ts
813
+ │ │ ├── PatternValidator.ts # Syntax + safety checks
814
+ │ │ ├── ErrorRecovery.ts # Retry / backoff
815
+ │ │ ├── PerformanceMonitor.ts
816
+ │ │ └── InputValidator.ts # Input bound checks
817
+ │ ├── StrudelController.ts # Browser automation (~800 lines)
818
+ │ ├── AudioAnalyzer.ts # Audio analysis (~800 lines)
819
+ │ ├── PatternStore.ts # On-disk pattern persistence
783
820
  │ └── index.ts # Entry point
784
- ├── tests/
785
- │ ├── browser-test.js # Browser integration
786
- │ ├── integration.test.js # Integration tests
787
- │ ├── manual-test.js # Manual testing
788
- │ ├── mcp-tools.test.ts # MCP tool tests
789
- │ └── strudel-integration.js # Full integration
790
- ├── patterns/ # Saved patterns
791
- ├── config.json # Server configuration
792
- ├── package.json # Dependencies
793
- └── tsconfig.json # TypeScript config
821
+ ├── src/__tests__/ # Jest suites (unit + integration + browser)
822
+ ├── patterns/
823
+ │ ├── examples/ # 18 bundled example patterns
824
+ │ └── *.json # Saved patterns at runtime
825
+ ├── scripts/
826
+ │ ├── generate-tool-docs.ts # README tool-table generator
827
+ │ └── generate-changelog.ts
828
+ ├── config.json # Local config (gitignored)
829
+ ├── package.json
830
+ └── tsconfig.json
794
831
  ```
795
832
 
796
833
  ### Data Flow
@@ -956,102 +993,49 @@ gh release create v$(node -p "require('./package.json').version") --generate-not
956
993
 
957
994
  The package uses OIDC trusted publishing with provenance attestation for supply chain security.
958
995
 
959
- ### Project Structure
960
-
961
- ```
962
- src/
963
- ├── server/
964
- │ └── server.ts # MCP server
965
- │
966
- ├── services/
967
- │ ├── MusicTheory.ts # Music theory engine
968
- │ │ - 15+ scales (major, minor, modes, etc.)
969
- │ │ - Chord progressions (jazz, pop, blues, etc.)
970
- │ │ - Euclidean rhythm generation
971
- │ │ - Arpeggio generation
972
- │ │
973
- │ └── PatternGenerator.ts # Pattern creation service
974
- │ - Genre-specific drum patterns
975
- │ - Bassline generation
976
- │ - Melody composition
977
- │ - Pattern variations
978
- │ - Complete track generation
979
- │
980
- ├── utils/
981
- │ ├── Logger.ts # Logging utility
982
- │ ├── PerformanceMonitor.ts # Performance tracking
983
- │ ├── PatternValidator.ts # Pattern syntax validation
984
- │ └── ErrorRecovery.ts # Error handling & recovery
985
- │
986
- ├── types/
987
- │ └── index.ts # TypeScript type definitions
988
- │
989
- ├── StrudelController.ts # Browser automation
990
- │ - Chromium management via Playwright
991
- │ - CodeMirror editor manipulation
992
- │ - Playback control
993
- │ - Pattern validation
994
- │ - Error recovery
995
- │
996
- ├── AudioAnalyzer.ts # Real-time audio analysis
997
- │ - Web Audio API injection
998
- │ - FFT spectral analysis
999
- │ - Frequency band detection
1000
- │ - Playing state monitoring
1001
- │
1002
- ├── PatternStore.ts # Pattern persistence
1003
- │ - JSON-based storage
1004
- │ - Tag-based organization
1005
- │ - Metadata tracking
1006
- │ - List caching
1007
- │
1008
- └── index.ts # Application entry point
1009
- ```
1010
-
1011
- ### Adding New Tools
1012
-
1013
- To add a new MCP tool:
1014
-
1015
- 1. **Define the tool** in `getTools()` method:
1016
- ```typescript
1017
- {
1018
- name: 'my_new_tool',
1019
- description: 'Description of what it does',
1020
- inputSchema: {
1021
- type: 'object',
1022
- properties: {
1023
- param1: { type: 'string', description: 'Parameter description' },
1024
- param2: { type: 'number', description: 'Numeric parameter' }
1025
- },
1026
- required: ['param1']
1027
- }
1028
- }
1029
- ```
996
+ ### Adding new tools
997
+
998
+ Tools live in per-domain modules under `src/server/tools/<domain>.ts`. `server.ts` just dispatches. To add a tool:
999
+
1000
+ 1. **Pick the right domain module** (or add a new one). Add the tool definition to that module's `tools` array:
1001
+
1002
+ ```typescript
1003
+ export const tools: Tool[] = [
1004
+ // ...
1005
+ {
1006
+ name: 'my_new_tool',
1007
+ description: 'One-line description; agents read this to pick between adjacent tools',
1008
+ inputSchema: {
1009
+ type: 'object',
1010
+ properties: {
1011
+ param1: { type: 'string', description: 'What it is' },
1012
+ session_id: { type: 'string', description: 'Optional session ID (#108)' },
1013
+ },
1014
+ required: ['param1'],
1015
+ },
1016
+ },
1017
+ ];
1018
+ ```
1030
1019
 
1031
- 2. **Implement the handler** in `executeTool()` switch statement:
1032
- ```typescript
1033
- case 'my_new_tool':
1034
- // Your implementation here
1035
- return await this.someService.doSomething(args.param1, args.param2);
1036
- ```
1020
+ 2. **Add the case** to the module's `execute()` switch:
1037
1021
 
1038
- 3. **Add necessary service methods** if needed:
1039
- ```typescript
1040
- // In appropriate service file
1041
- async doSomething(param1: string, param2?: number): Promise<string> {
1042
- // Implementation
1043
- return `Result: ${param1}`;
1044
- }
1045
- ```
1022
+ ```typescript
1023
+ case 'my_new_tool':
1024
+ return await ctx.getController(args.session_id).doSomething(args.param1);
1025
+ ```
1046
1026
 
1047
- 4. **Test the tool**:
1048
- ```bash
1049
- # Build
1050
- npm run build
1027
+ 3. **Add a service method** if needed (`MusicTheory`, `PatternGenerator`, etc.) and surface it through `ToolContext` (`src/server/tools/types.ts`) if other modules need it.
1051
1028
 
1052
- # Test via MCP
1053
- echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"my_new_tool","arguments":{"param1":"test"}},"id":2}' | node dist/index.js
1054
- ```
1029
+ 4. **Don't hand-edit the README tool table.** It auto-generates via `npm run build` → `scripts/generate-tool-docs.ts`. A Jest test plus a CI step guard against drift.
1030
+
1031
+ 5. **Use the envelope helpers** for returns: `ok(data)`, `empty(data)`, `err('validation', 'message')` from `src/server/tools/types.ts`. Raw returns still work — the dispatcher normalises them — but native envelope construction is clearer.
1032
+
1033
+ 6. **Build and test**:
1034
+
1035
+ ```bash
1036
+ npm run build
1037
+ echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"my_new_tool","arguments":{"param1":"test"}},"id":2}' | node dist/index.js
1038
+ ```
1055
1039
 
1056
1040
  ### Testing Strategy
1057
1041
 
@@ -1074,7 +1058,7 @@ npm run test:integration
1074
1058
  # - Pattern generation
1075
1059
  # - Audio analysis
1076
1060
  # - Pattern storage
1077
- # - All 65 tools
1061
+ # - All 84 registered tools
1078
1062
  ```
1079
1063
 
1080
1064
  #### 3. Manual Testing
@@ -1289,12 +1273,19 @@ SMOOTHING=0.8
1289
1273
 
1290
1274
  ## Performance
1291
1275
 
1292
- - **Pattern Generation**: <100ms
1293
- - **Browser Initialization**: ~3 seconds
1294
- - **Pattern Writing**: Instant
1295
- - **Playback Start**: ~500ms
1296
- - **Audio Analysis**: Real-time
1297
- - **Memory Usage**: <150MB
1276
+ Measured against the current `StrudelController` cache + Strudel.cc on a developer machine:
1277
+
1278
+ | Operation | Latency |
1279
+ |---|---|
1280
+ | Browser initialization | 1.5–2 s (with resource blocking) |
1281
+ | Pattern write | 50–80 ms (cached CodeMirror editor access) |
1282
+ | Pattern read (cached) | 10–15 ms |
1283
+ | Play / pause / stop | 100–150 ms |
1284
+ | Audio analysis (single FFT) | 10–15 ms |
1285
+ | Tempo detection | <100 ms (onset-based; degraded under headless audio) |
1286
+ | Key detection | <100 ms (Krumhansl-Schmuckler) |
1287
+ | Pattern generation | <100 ms (template-based) |
1288
+ | Process resident memory | ~120–150 MB |
1298
1289
 
1299
1290
  ## Advanced Usage
1300
1291
 
@@ -1555,7 +1546,7 @@ npm run build
1555
1546
  # Check if server responds
1556
1547
  echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js
1557
1548
 
1558
- # Should return JSON with 65 tools
1549
+ # Should return JSON with 84 tools (post-v3.0; ~26 after #178 alias removal)
1559
1550
 
1560
1551
  # Reinstall MCP server in Claude
1561
1552
  claude mcp remove strudel
@@ -1734,6 +1725,6 @@ Earlier versions of this package (including `@williamzujkowski/strudel-mcp-serve
1734
1725
 
1735
1726
  ---
1736
1727
 
1737
- **v2.4.0** - Open Source | Experimental | [Report Issues](https://github.com/williamzujkowski/live-coding-music-mcp/issues) | [Contribute](https://github.com/williamzujkowski/live-coding-music-mcp/pulls)
1728
+ **v3.0.0** — Open source, AGPL-3.0-or-later, experimental | [Report issues](https://github.com/williamzujkowski/live-coding-music-mcp/issues) | [Contribute](https://github.com/williamzujkowski/live-coding-music-mcp/pulls)
1738
1729
 
1739
1730
  *This project is under active development. Core features work, but expect bugs and breaking changes. Not recommended for production use.*