@williamzujkowski/live-coding-music-mcp 1.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/LICENSE +661 -21
- package/README.md +228 -233
- package/dist/AudioAnalyzer.js +0 -1
- package/dist/PatternStore.js +0 -1
- package/dist/index.js +0 -0
- package/dist/server/resources.js +175 -0
- package/dist/server/server.js +226 -348
- package/dist/server/tools/ai.js +78 -22
- package/dist/server/tools/analysis.js +266 -73
- package/dist/server/tools/capture.js +67 -20
- package/dist/server/tools/compose.js +159 -0
- package/dist/server/tools/diagnostics.js +112 -60
- package/dist/server/tools/editor.js +130 -66
- package/dist/server/tools/generate.js +190 -74
- package/dist/server/tools/history.js +149 -88
- package/dist/server/tools/playback.js +49 -18
- package/dist/server/tools/session.js +108 -70
- package/dist/server/tools/storage.js +86 -30
- package/dist/server/tools/transform.js +250 -116
- package/dist/server/tools/types.js +66 -1
- package/dist/services/AudioCaptureService.js +4 -3
- package/dist/services/GeminiService.js +1 -1
- package/dist/services/MIDIExportService.js +2 -4
- package/dist/services/SessionManager.js +4 -2
- package/dist/services/StrudelEngine.js +24 -126
- package/dist/services/StrudelEngineHelpers.js +151 -0
- package/package.json +2 -2
- package/dist/__tests__/MusicTheory.test.js +0 -245
- package/dist/__tests__/PatternGenerator.test.js +0 -337
- package/dist/__tests__/PatternStore.test.js +0 -153
- package/dist/__tests__/utils/MockPlaywright.js +0 -130
- package/dist/server/EnhancedMCPServer.js +0 -654
- package/dist/server/EnhancedMCPServerFixed.js +0 -2506
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 |
|
|
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
|
[](https://github.com/williamzujkowski/live-coding-music-mcp/actions)
|
|
14
14
|
[](https://www.npmjs.com/package/@williamzujkowski/live-coding-music-mcp)
|
|
15
15
|
[](https://nerq.ai/kya/live-coding-music-mcp)
|
|
16
|
-
[]()
|
|
17
|
+
[](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
|
|
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
|
-
-
|
|
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
|
-
### 🎹
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
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
|
|
66
|
+
### 🎼 Example patterns
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
18 example patterns ship in [`patterns/examples/`](patterns/examples/), grouped by genre:
|
|
68
69
|
|
|
69
|
-
- **Techno**:
|
|
70
|
-
- **House**:
|
|
71
|
-
- **Drum & Bass**:
|
|
72
|
-
- **Ambient**:
|
|
73
|
-
- **Trap**:
|
|
74
|
-
- **Jungle**:
|
|
75
|
-
- **Jazz**:
|
|
76
|
-
- **
|
|
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
|
|
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 |
|
|
160
|
-
|
|
158
|
+
| Action | Tool call |
|
|
159
|
+
|---|---|
|
|
161
160
|
| Initialize browser | `init` |
|
|
162
|
-
| Create techno beat | `
|
|
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
|
-
|
|
|
168
|
-
|
|
|
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
|
-
**
|
|
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` |
|
|
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.
|
|
303
|
-
| `jam_with` | AI generates a complementary layer to jam with your pattern.
|
|
304
|
-
| `shift_mood` | Transform current pattern to match a different emotional mood
|
|
305
|
-
| `refine` |
|
|
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` |
|
|
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` |
|
|
328
|
-
| `destroy_session` | Close and destroy a Strudel session
|
|
329
|
-
| `list_sessions` | List all active Strudel sessions
|
|
330
|
-
| `switch_session` |
|
|
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
|
|
348
|
-
| `stop_audio_capture` | Stop audio capture and return
|
|
349
|
-
| `capture_audio_sample` |
|
|
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
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
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> (
|
|
369
|
+
<details><summary><strong>Other</strong> (19)</summary>
|
|
366
370
|
|
|
367
371
|
| Tool | Description |
|
|
368
372
|
|------|-------------|
|
|
369
|
-
| `
|
|
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.
|
|
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
|
-
|
|
663
|
-
-
|
|
664
|
-
-
|
|
665
|
-
-
|
|
666
|
-
-
|
|
667
|
-
-
|
|
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
|
-
│ │
|
|
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 #
|
|
775
|
-
│ │
|
|
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
|
-
│ │
|
|
778
|
-
│ ├──
|
|
779
|
-
│ │
|
|
780
|
-
│ ├──
|
|
781
|
-
│
|
|
782
|
-
│ ├──
|
|
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
|
-
├──
|
|
785
|
-
|
|
786
|
-
│ ├──
|
|
787
|
-
│
|
|
788
|
-
|
|
789
|
-
│
|
|
790
|
-
|
|
791
|
-
├── config.json #
|
|
792
|
-
├── package.json
|
|
793
|
-
└── tsconfig.json
|
|
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
|
-
###
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
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. **
|
|
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
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1053
|
-
|
|
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
|
|
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
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
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
|
|
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
|
|
@@ -1719,7 +1710,11 @@ We review PRs promptly and welcome contributors of all skill levels. See [DEVELO
|
|
|
1719
1710
|
|
|
1720
1711
|
## 📄 License
|
|
1721
1712
|
|
|
1722
|
-
|
|
1713
|
+
**AGPL-3.0-or-later** — see [LICENSE](LICENSE) for the full text.
|
|
1714
|
+
|
|
1715
|
+
This project depends on `@strudel/core`, `@strudel/mini`, `@strudel/tonal`, and `@strudel/transpiler`, which are AGPL-3.0 licensed by the upstream [Strudel project](https://codeberg.org/uzu/strudel). Since we `import` from those packages and redistribute the combined work via npm, this project must be distributed under the same copyleft terms. If you fork or redistribute, you must keep the AGPL license and provide source access to any network-accessible users (AGPL §13).
|
|
1716
|
+
|
|
1717
|
+
Earlier versions of this package (including `@williamzujkowski/strudel-mcp-server` prior to deprecation) shipped with an MIT declaration — that was incorrect given the AGPL dependencies. v2.0.0 of `@williamzujkowski/live-coding-music-mcp` corrects the license to AGPL-3.0-or-later. v1.0.0 of this package is deprecated; install v2.0.0 or later.
|
|
1723
1718
|
|
|
1724
1719
|
## 🙏 Acknowledgments
|
|
1725
1720
|
|
|
@@ -1730,6 +1725,6 @@ MIT License - see [LICENSE](LICENSE) file
|
|
|
1730
1725
|
|
|
1731
1726
|
---
|
|
1732
1727
|
|
|
1733
|
-
**
|
|
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)
|
|
1734
1729
|
|
|
1735
1730
|
*This project is under active development. Core features work, but expect bugs and breaking changes. Not recommended for production use.*
|