@williamzujkowski/live-coding-music-mcp 4.0.0 → 4.1.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 +202 -705
- package/dist/AudioAnalyzer.js +1294 -91
- package/dist/PatternStore.js +276 -23
- package/dist/StrudelController.js +388 -56
- package/dist/server/resources.js +27 -20
- package/dist/server/server.js +384 -76
- package/dist/server/tools/ai.js +124 -91
- package/dist/server/tools/analysis.js +168 -59
- package/dist/server/tools/capture.js +135 -24
- package/dist/server/tools/compose.js +26 -26
- package/dist/server/tools/diagnostics.js +20 -3
- package/dist/server/tools/editor.js +60 -6
- package/dist/server/tools/generate.js +38 -15
- package/dist/server/tools/history.js +30 -8
- package/dist/server/tools/playback.js +2 -1
- package/dist/server/tools/session.js +38 -6
- package/dist/server/tools/storage.js +179 -8
- package/dist/server/tools/transform.js +127 -43
- package/dist/server/tools/types.js +209 -14
- package/dist/services/AudioCaptureService.js +302 -33
- package/dist/services/AudioExportService.js +318 -0
- package/dist/services/BrowserOnlyFunctions.js +149 -0
- package/dist/services/EventDensityProbe.js +324 -0
- package/dist/services/GeminiService.js +221 -36
- package/dist/services/IsolatedEngineRunner.js +308 -0
- package/dist/services/IsolatedStrudelEngine.js +135 -0
- package/dist/services/LocalPatternEngine.js +16 -0
- package/dist/services/MIDIExportService.js +765 -71
- package/dist/services/MIDIImportService.js +474 -0
- package/dist/services/MusicTheory.js +85 -13
- package/dist/services/PatternGenerator.js +168 -85
- package/dist/services/PatternSandbox.js +359 -0
- package/dist/services/SessionManager.js +338 -65
- package/dist/services/StrudelEngine.js +218 -12
- package/dist/services/StrudelEngineHelpers.js +24 -8
- package/dist/services/StyleRegistry.js +204 -0
- package/dist/services/Transferable.js +114 -0
- package/dist/services/ai/AiTransport.js +56 -0
- package/dist/services/ai/AudioMeasurements.js +155 -0
- package/dist/services/ai/CliTransport.js +256 -0
- package/dist/services/engineChild.js +83 -0
- package/dist/services/engineChildPath.js +28 -0
- package/dist/utils/CategorisedError.js +59 -0
- package/dist/utils/ErrorRecovery.js +130 -110
- package/dist/utils/InputValidator.js +55 -7
- package/dist/utils/PatternValidator.js +136 -17
- package/dist/utils/SafePath.js +112 -0
- package/dist/utils/ServerConfig.js +248 -0
- package/dist/utils/TableLookup.js +41 -0
- package/dist/utils/Tempo.js +143 -0
- package/package.json +17 -5
- package/dist/services/__mocks__/StrudelEngine.js +0 -157
- package/dist/types/index.js +0 -1
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 | 88% 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,12 +13,12 @@
|
|
|
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
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 →
|
|
21
|
+
**Current State: Beta.** The core workflow (init → compose → playback → analyze) works reliably with real audio output. `npm test` reports ~3060 passing tests, <!-- COVERAGE:START -->88.99% statement coverage / 79.99% branch coverage<!-- COVERAGE:END -->. 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
|
|
@@ -30,8 +30,8 @@ A Model Context Protocol (MCP) server that drives [Strudel.cc](https://strudel.c
|
|
|
30
30
|
|
|
31
31
|
- [Features](#features)
|
|
32
32
|
- [Installation](#installation)
|
|
33
|
-
- [Quick Reference](#quick-reference)
|
|
34
33
|
- [Quick Start](#quick-start)
|
|
34
|
+
- [Quick Reference](#quick-reference)
|
|
35
35
|
- [Available Tools](#available-tools)
|
|
36
36
|
- [Usage Examples](#usage-examples)
|
|
37
37
|
- [Architecture](#architecture)
|
|
@@ -44,39 +44,40 @@ A Model Context Protocol (MCP) server that drives [Strudel.cc](https://strudel.c
|
|
|
44
44
|
|
|
45
45
|
## Features
|
|
46
46
|
|
|
47
|
-
###
|
|
48
|
-
- **
|
|
47
|
+
### Music control
|
|
48
|
+
- **28 MCP tools** covering pattern editing, playback, audio analysis, generation, history, sessions, MIDI import/export, and Gemini-backed assists. Each tool is enum-parameterized to keep the protocol surface small: `pattern_store({ action })`, `edit_pattern({ mode })`, `transform({ op })`, `analyze({ include })`, `history({ action })`, `playback({ action })`, `effect({ action })`, `shape({ dimension })`, `audio_capture({ action })`, `browser_window({ action })`, `generate_part({ role })`, `generate_rhythm({ type })`, `music_theory({ query })`, `session({ action })`, `ai_assist({ task })`, ... The 58 legacy single-verb aliases that forwarded to these were removed in v4.0.0 ([#178](https://github.com/williamzujkowski/live-coding-music-mcp/issues/178)).
|
|
49
49
|
- **4 MCP resources** for catalog browsing without burning tool calls: `strudel://examples`, `strudel://patterns`, `strudel://styles`, `strudel://docs/tools`.
|
|
50
50
|
- **Real browser automation** of Strudel.cc through Playwright.
|
|
51
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
52
|
- **Audio analysis** via Web Audio API (FFT spectrum, tempo detection, key detection, rhythm complexity).
|
|
53
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**:
|
|
54
|
+
- **Music theory helpers**: 14 scales, 8 chord progression styles, euclidean and polyrhythm generation.
|
|
55
55
|
- **Pattern persistence**: JSON-backed save/load with tags + the in-memory edit history (undo/redo/restore/compare).
|
|
56
56
|
- **Result envelope** on every `tools/call`: clients branch on `{ ok, errorCategory, isRetryable }` instead of parsing free-text.
|
|
57
57
|
|
|
58
|
-
###
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
- **
|
|
58
|
+
### Testing & CI status
|
|
59
|
+
- **~3060 passing tests**: `npm test` runs ~3020 unit/integration/example tests in parallel, then 36 browser-validation tests serially against real Chromium. The coverage figure below is from the first tier, which is the one CI also runs — the browser tier adds ~0.2 points and CI does not execute it, so counting it would document coverage nothing verifies.
|
|
60
|
+
<!-- COVERAGE:START -->
|
|
61
|
+
- **88.99% statement coverage / 79.99% branch coverage** (90.5% functions, 89.75% lines), checked against `coverage/coverage-summary.json` by a drift guard.
|
|
62
|
+
<!-- COVERAGE:END -->
|
|
63
|
+
- **Lint blocking in CI**: 0 errors, ~195 warnings (mostly `any` in test mocks).
|
|
62
64
|
- **OIDC trusted publishing** to npm with SLSA build provenance attestation on every release.
|
|
63
65
|
|
|
64
|
-
**Not Production-Ready:** This is experimental software under active development. Use for exploration and experimentation. Expect breaking changes, bugs, and incomplete features. See [
|
|
66
|
+
**Not Production-Ready:** This is experimental software under active development. Use for exploration and experimentation. Expect breaking changes, bugs, and incomplete features. See [the Contributing section](#contributing) to help improve it.
|
|
65
67
|
|
|
66
|
-
###
|
|
68
|
+
### Example patterns
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
7 example patterns ship in [`patterns/examples/`](patterns/examples/), grouped by genre:
|
|
69
71
|
|
|
70
|
-
- **
|
|
71
|
-
- **
|
|
72
|
-
- **
|
|
73
|
-
- **
|
|
74
|
-
- **
|
|
75
|
-
- **
|
|
76
|
-
- **
|
|
77
|
-
- **Longform** (multi-minute pieces): dark-ambient-journey, driving-techno, liquid-dnb-roller, nu-jazz-session
|
|
72
|
+
- **Ambient**: ambient-pad (70 BPM)
|
|
73
|
+
- **Dnb**: dnb-classic (174 BPM)
|
|
74
|
+
- **House**: house-classic (125 BPM)
|
|
75
|
+
- **Jazz**: jazz-ii-v-i (120 BPM)
|
|
76
|
+
- **Jungle**: amen-break (165 BPM)
|
|
77
|
+
- **Techno**: techno-driving (130 BPM)
|
|
78
|
+
- **Trap**: trap-modern (140 BPM)
|
|
78
79
|
|
|
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.
|
|
80
|
+
Each example is a JSON file with pattern code, BPM, key, and a description, and each sets the tempo it declares (#367). 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.
|
|
80
81
|
|
|
81
82
|
## Migrating from `@williamzujkowski/strudel-mcp-server`
|
|
82
83
|
|
|
@@ -151,9 +152,86 @@ npx playwright install chromium
|
|
|
151
152
|
npm run build
|
|
152
153
|
```
|
|
153
154
|
|
|
155
|
+
## Quick Start
|
|
156
|
+
|
|
157
|
+
Get from install to your first generated pattern in under two minutes.
|
|
158
|
+
|
|
159
|
+
### 1. Install
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npm install -g @williamzujkowski/live-coding-music-mcp
|
|
163
|
+
npx playwright install chromium # one-time
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Building from source instead? See [Installation → From Source](#from-source).
|
|
167
|
+
|
|
168
|
+
### 2. Configure your MCP client
|
|
169
|
+
|
|
170
|
+
#### Claude Desktop
|
|
171
|
+
|
|
172
|
+
Edit your Claude Desktop config file:
|
|
173
|
+
|
|
174
|
+
| OS | Config path |
|
|
175
|
+
|---|---|
|
|
176
|
+
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
177
|
+
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
|
|
178
|
+
| Linux | `~/.config/Claude/claude_desktop_config.json` |
|
|
179
|
+
|
|
180
|
+
Add the server:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"mcpServers": {
|
|
185
|
+
"live-coding-music": {
|
|
186
|
+
"command": "live-coding-music-mcp"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Restart Claude Desktop. The server appears under the 🔌 plug icon.
|
|
193
|
+
|
|
194
|
+
#### Claude Code (CLI)
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# If installed globally
|
|
198
|
+
claude mcp add strudel live-coding-music-mcp
|
|
199
|
+
|
|
200
|
+
# If built from source
|
|
201
|
+
claude mcp add strudel node /path/to/live-coding-music-mcp/dist/index.js
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### 3. Verify the server responds
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# From a global install
|
|
208
|
+
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | live-coding-music-mcp
|
|
209
|
+
|
|
210
|
+
# From source
|
|
211
|
+
npm run validate
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
You should see a JSON response listing **28 tools**. If you see fewer, the build is out of date — run `npm run build`.
|
|
215
|
+
|
|
216
|
+
### 4. Make your first sound
|
|
217
|
+
|
|
218
|
+
In Claude, ask:
|
|
219
|
+
|
|
220
|
+
> Initialize Strudel and compose a techno beat.
|
|
221
|
+
|
|
222
|
+
**What you'll see:** A Chromium window opens (visibly — this is the live editor, not a hidden process) and lands on strudel.cc. Claude calls `init`, then `compose({ style: "techno" })`. A 4-on-the-floor pattern appears in the CodeMirror editor and starts playing through your speakers.
|
|
223
|
+
|
|
224
|
+
Prefer headless mode (no browser window)? Set `"headless": true` in `config.json` before the first `init` call — see [Configuration](#configuration). Note that tempo detection currently reflects how often the agent polls rather than the audio itself (#322), in headed or headless mode alike.
|
|
225
|
+
|
|
226
|
+
### 5. Where to go next
|
|
227
|
+
|
|
228
|
+
- [Quick Reference](#quick-reference) below: tool cheat sheet for common operations.
|
|
229
|
+
- [Usage Examples](#usage-examples): multi-step workflows (composition, audio analysis, AI-assisted jamming).
|
|
230
|
+
- [`patterns/examples/`](patterns/examples/): 18 ready-to-play patterns across 7 genres plus 4 longform pieces. Agents can browse them via the `strudel://examples` MCP resource without burning tool calls.
|
|
231
|
+
|
|
154
232
|
## Quick Reference
|
|
155
233
|
|
|
156
|
-
Common
|
|
234
|
+
Common operations as one-line tool calls:
|
|
157
235
|
|
|
158
236
|
| Action | Tool call |
|
|
159
237
|
|---|---|
|
|
@@ -173,35 +251,14 @@ The legacy single-verb tools (`play`, `stop`, `save`, `undo`, `write`, `generate
|
|
|
173
251
|
|
|
174
252
|
**One-shot workflow:**
|
|
175
253
|
```
|
|
176
|
-
compose with style: "dnb", key: "Am",
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Quick Start
|
|
180
|
-
|
|
181
|
-
### 1. Add to Claude
|
|
182
|
-
```bash
|
|
183
|
-
# If installed globally
|
|
184
|
-
claude mcp add strudel live-coding-music-mcp
|
|
185
|
-
|
|
186
|
-
# If built from source
|
|
187
|
-
claude mcp add strudel node /path/to/live-coding-music-mcp/dist/index.js
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### 2. Start Using
|
|
191
|
-
```bash
|
|
192
|
-
claude chat
|
|
254
|
+
compose with style: "dnb", key: "Am", tempo: 174, auto_play: true
|
|
193
255
|
```
|
|
194
256
|
|
|
195
|
-
Then ask Claude:
|
|
196
|
-
- "Initialize Strudel and create a techno beat"
|
|
197
|
-
- "Generate a jazz chord progression in F major"
|
|
198
|
-
- "Create a drum & bass pattern at 174 BPM"
|
|
199
|
-
|
|
200
257
|
## Available Tools
|
|
201
258
|
|
|
202
259
|
<!-- TOOLS:START -->
|
|
203
260
|
|
|
204
|
-
**
|
|
261
|
+
**28 tools** across 15 categories:
|
|
205
262
|
|
|
206
263
|
<details><summary><strong>Setup</strong> (1)</summary>
|
|
207
264
|
|
|
@@ -215,7 +272,7 @@ Then ask Claude:
|
|
|
215
272
|
|
|
216
273
|
| Tool | Description |
|
|
217
274
|
|------|-------------|
|
|
218
|
-
| `edit_pattern` | Mutate the current session pattern.
|
|
275
|
+
| `edit_pattern` | Mutate the current session pattern. mode=write replaces the editor contents (default; mirrors the old write tool exactly, including optional pattern validation and auto_play). mode=append concatenates `code` after the current pattern with a newline. mode=insert places `code` at the given line `position`. mode=replace substitutes `search` with `replace` — the first occurrence only, unless replace_all is true. The response reports how many occurrences matched, were replaced, and remain. mode=clear empties the editor. Example: edit_pattern({ mode: "write", pattern: "s(\"bd\")", auto_play: true }). For reading the editor without mutating it use get_pattern; for the on-disk pattern catalog use pattern_store. |
|
|
219
276
|
| `get_pattern` | Get current pattern code |
|
|
220
277
|
|
|
221
278
|
</details>
|
|
@@ -224,16 +281,17 @@ Then ask Claude:
|
|
|
224
281
|
|
|
225
282
|
| Tool | Description |
|
|
226
283
|
|------|-------------|
|
|
227
|
-
| `playback` | Control transport on the current session.
|
|
228
|
-
| `set_tempo` | Set BPM |
|
|
284
|
+
| `playback` | Control transport on the current session. action=play starts the editor pattern. action=pause halts the clock where it is, so play resumes mid-cycle. action=stop ends playback. Example: playback({ action: "play" }). For pattern editing use edit_pattern; for tempo use set_tempo. |
|
|
285
|
+
| `set_tempo` | Set BPM. Writes setcpm(bpm/4), assuming one bar of 4/4 per cycle. |
|
|
229
286
|
|
|
230
287
|
</details>
|
|
231
288
|
|
|
232
|
-
<details><summary><strong>Storage</strong> (
|
|
289
|
+
<details><summary><strong>Storage</strong> (2)</summary>
|
|
233
290
|
|
|
234
291
|
| Tool | Description |
|
|
235
292
|
|------|-------------|
|
|
236
|
-
| `pattern_store` | Persist patterns to disk and read them back.
|
|
293
|
+
| `pattern_store` | Persist patterns to disk and read them back. Use action=save to write the current session pattern under a name; action=load to restore a named pattern into the current session; action=list to enumerate the on-disk catalog (optionally filtered by tag). Example: pattern_store({ action: "save", name: "my-jam", tags: ["techno"] }). For session lifecycle (create/destroy/list active sessions) use the session tool — pattern_store deals with on-disk patterns, not runtime sessions. |
|
|
294
|
+
| `import_midi` | Convert a .mid file into a playable Strudel pattern (Phase 1: literal transcription, #201). Use source="base64" with data=<base64 string> for inline bytes, or source="path" with data=<basename> to read from the patterns/midi/ directory (path traversal blocked). Drum tracks (MIDI channel 10) emit one s() lane per sample so simultaneous kicks/hats do not collide. Pitched tracks emit note("...").s("piano") with simultaneous notes merged into [a,b,c] chord tokens. Phase 2+ (structural compression, voice separation, LLM idiomatic pass) tracked in separate issues. Example: import_midi({ source: "path", data: "drumloop.mid", steps_per_cycle: 16 }). For the reverse direction (Strudel → MIDI) use the export_midi tool. |
|
|
237
295
|
|
|
238
296
|
</details>
|
|
239
297
|
|
|
@@ -241,7 +299,7 @@ Then ask Claude:
|
|
|
241
299
|
|
|
242
300
|
| Tool | Description |
|
|
243
301
|
|------|-------------|
|
|
244
|
-
| `history` | Navigate or inspect the pattern edit history.
|
|
302
|
+
| `history` | Navigate or inspect the pattern edit history. action=undo reverts the last edit on the targeted session. action=redo replays a previously-undone edit. action=list returns recent entries with timestamps and previews (limit defaults to 10). action=restore jumps the editor to a specific entry by id (current pattern goes on the undo stack). action=compare diffs two entries by id (or one entry vs current pattern). Example: history({ action: "list", limit: 5 }) — recent edits, newest first. For on-disk saved patterns use pattern_store — history deals with the in-memory edit timeline of the current session. |
|
|
245
303
|
|
|
246
304
|
</details>
|
|
247
305
|
|
|
@@ -250,8 +308,8 @@ Then ask Claude:
|
|
|
250
308
|
| Tool | Description |
|
|
251
309
|
|------|-------------|
|
|
252
310
|
| `compose` | Generate, write, and play a complete pattern in one step. Auto-initializes default browser if needed. |
|
|
253
|
-
| `generate_part` | Generate a single instrumental layer and append it to the current session pattern.
|
|
254
|
-
| `generate_rhythm` | Generate a rhythmic pattern and append it to the current session.
|
|
311
|
+
| `generate_part` | Generate a single instrumental layer and append it to the current session pattern. role=drums takes `style` (e.g. "techno"/"house") and optional `complexity` 0-1. role=bass takes `key` (e.g. "C") + `style`. role=melody takes `root`/`scale` (e.g. C/minor) and optional `length` (notes). role=fill takes `style` and optional `bars`. Example: generate_part({ role: "drums", style: "techno", complexity: 0.7 }). For full compositions use compose; for rhythmic patterns use generate_rhythm; for music-theory queries use music_theory. |
|
|
312
|
+
| `generate_rhythm` | Generate a rhythmic pattern and append it to the current session. type=euclidean produces a Euclidean rhythm with `hits` evenly distributed across `steps` (optional `sound` param, default "bd"). type=polyrhythm overlays multiple sound layers with given pattern numbers. Example: generate_rhythm({ type: "euclidean", hits: 3, steps: 8, sound: "hh" }). For complete patterns (drums/bass/melody) use generate_part; for whole compositions use compose. |
|
|
255
313
|
|
|
256
314
|
</details>
|
|
257
315
|
|
|
@@ -259,7 +317,7 @@ Then ask Claude:
|
|
|
259
317
|
|
|
260
318
|
| Tool | Description |
|
|
261
319
|
|------|-------------|
|
|
262
|
-
| `music_theory` | Music-theory queries.
|
|
320
|
+
| `music_theory` | Music-theory queries. query=scale returns the notes of a scale (e.g. "C major scale: C, D, E, F, G, A, B"). query=chord_progression returns a chord progression for the key/style AND writes the resulting chord pattern into the current session. Example: music_theory({ query: "scale", root: "C", scale: "major" }). For pattern generation (drums/bass/melody) use generate_part; for rhythmic patterns use generate_rhythm. |
|
|
263
321
|
|
|
264
322
|
</details>
|
|
265
323
|
|
|
@@ -267,9 +325,9 @@ Then ask Claude:
|
|
|
267
325
|
|
|
268
326
|
| Tool | Description |
|
|
269
327
|
|------|-------------|
|
|
270
|
-
| `transform` | Apply a single transform op to the current session pattern.
|
|
271
|
-
| `effect` | Add or remove a Strudel effect on the current session pattern.
|
|
272
|
-
| `shape` | Shape the current pattern along one of three high-level dimensions.
|
|
328
|
+
| `transform` | Apply a single transform op to the current session pattern. op=transpose shifts notes by `semitones`. op=reverse appends `.rev` to the pattern. op=stretch slows by `factor` (>1 slower, <1 faster). op=quantize snaps to the `grid` (e.g. "1/16"). op=humanize adds rand-nudge timing of `amount` (0-1). op=swing applies `.swing(amount)`. op=scale applies a `root`/`scale` filter to notes. op=vary returns a variation of `type` (subtle/moderate/extreme/glitch/evolving). Example: transform({ op: "transpose", semitones: 7 }). For effects (add/remove) use effect; for mood/energy/refine use shape; for tempo use set_tempo. |
|
|
329
|
+
| `effect` | Add or remove a Strudel effect on the current session pattern. action=add appends `.<effect>(<params>)`. action=remove strips EVERY `.<effect>(...)` call from the pattern, not just the last. Example: effect({ action: "add", effect: "lpf", params: "1000" }). For higher-level effect bundles (mood/energy/refine) use shape; for raw transforms use transform. |
|
|
330
|
+
| `shape` | Shape the current pattern along one of three high-level dimensions. dimension=mood applies a mood profile (dark/euphoric/melancholic/aggressive/dreamy/peaceful/energetic) with optional intensity 0-1. dimension=energy applies an energy level (integer 0-10). dimension=refine applies a directional refinement: faster/slower/louder/quieter/brighter/darker/"more reverb"/drier. All three auto-play by default. Example: shape({ dimension: "mood", target_mood: "dark", intensity: 0.8 }). For raw transform ops use transform; for explicit effects use effect. |
|
|
273
331
|
|
|
274
332
|
</details>
|
|
275
333
|
|
|
@@ -277,7 +335,7 @@ Then ask Claude:
|
|
|
277
335
|
|
|
278
336
|
| Tool | Description |
|
|
279
337
|
|------|-------------|
|
|
280
|
-
| `ai_assist` | Gemini-backed pattern assistance.
|
|
338
|
+
| `ai_assist` | Gemini-backed pattern assistance. task=feedback returns creative critique on the current pattern (optionally with audio analysis). task=suggest analyzes the currently playing audio and suggests a complementary Strudel pattern as text (not auto-executed). task=jam generates a fresh layer (drums/bass/melody/pad/texture) and merges it into the current pattern, then auto-plays. All three share Gemini auth + rate limiting. Example: ai_assist({ task: "jam", layer: "bass" }). Needs GEMINI_API_KEY, or a logged-in claude/agy/codex CLI on PATH (#252). For non-AI pattern generation use generate_part; for full compositions use compose. |
|
|
281
339
|
|
|
282
340
|
</details>
|
|
283
341
|
|
|
@@ -285,9 +343,9 @@ Then ask Claude:
|
|
|
285
343
|
|
|
286
344
|
| Tool | Description |
|
|
287
345
|
|------|-------------|
|
|
288
|
-
| `analyze` | Audio analysis on the currently-playing pattern.
|
|
346
|
+
| `analyze` | Audio analysis on the currently-playing pattern. include=["all"] (default) returns the full spectrum + features object, matching the pre-consolidation behaviour. include=["tempo"] returns only BPM with confidence. include=["key"] returns detected key + scale + confidence. include=["spectrum"] returns FFT features (bass, mid, treble, brightness, etc.). include=["rhythm"] returns rhythm-only analysis (complexity, density, syncopation). Combining values returns an object keyed by category, e.g. analyze({ include: ["tempo", "key"] }) → { tempo: {...}, key: {...} }. Example: analyze({ include: ["tempo"] }) to cheaply re-check BPM during a session. For static pattern analysis (no browser) use analyze_pattern_local; for runtime validation use validate_pattern_runtime. |
|
|
289
347
|
| `validate_pattern_runtime` | Validate pattern with runtime error checking (monitors Strudel console for errors) |
|
|
290
|
-
| `validate_pattern_local` | Validate pattern syntax against the in
|
|
348
|
+
| `validate_pattern_local` | Validate pattern syntax against the local StrudelEngine, which runs in a sandboxed child process (no browser required) |
|
|
291
349
|
| `analyze_pattern_local` | Static analysis (events/cycle, complexity, optional BPM) without browser playback |
|
|
292
350
|
| `query_pattern_events` | Enumerate events the pattern would emit between two cycle indices (max 16 cycles) |
|
|
293
351
|
| `transpile_pattern` | Transpile pattern source via StrudelEngine; returns transpiled code or syntax error |
|
|
@@ -298,7 +356,7 @@ Then ask Claude:
|
|
|
298
356
|
|
|
299
357
|
| Tool | Description |
|
|
300
358
|
|------|-------------|
|
|
301
|
-
| `session` | Manage isolated Strudel browser sessions (multi-session, #108).
|
|
359
|
+
| `session` | Manage isolated Strudel browser sessions (multi-session, #108). action=create starts a new named session (sessions share one browser but isolated contexts). action=destroy closes a named session and releases its resources. action=list returns metadata for all active sessions (id, created, last_activity, is_playing, is_default). action=switch changes the default session that subsequent tool calls route to when no session_id is passed. Example: session({ action: "create", session_id: "live-set-1" }). For the on-disk pattern catalog use pattern_store(action=list) — session(action=list) lists *runtime* sessions, not saved patterns. |
|
|
302
360
|
|
|
303
361
|
</details>
|
|
304
362
|
|
|
@@ -307,7 +365,7 @@ Then ask Claude:
|
|
|
307
365
|
| Tool | Description |
|
|
308
366
|
|------|-------------|
|
|
309
367
|
| `export_midi` | Export current pattern to MIDI file. Parses note(), n(), and chord() functions. |
|
|
310
|
-
| `browser_window` | Interact with the visible Strudel browser window.
|
|
368
|
+
| `browser_window` | Interact with the visible Strudel browser window. action=show brings the window to the foreground. action=screenshot captures the current editor view to disk (optional `filename`). Example: browser_window({ action: "screenshot", filename: "demo.png" }). For diagnostics (status/errors/perf) use diagnostics; for the editor itself use edit_pattern. |
|
|
311
369
|
|
|
312
370
|
</details>
|
|
313
371
|
|
|
@@ -315,7 +373,7 @@ Then ask Claude:
|
|
|
315
373
|
|
|
316
374
|
| Tool | Description |
|
|
317
375
|
|------|-------------|
|
|
318
|
-
| `audio_capture` | Record audio output from the live Strudel session.
|
|
376
|
+
| `audio_capture` | Record audio output from the live Strudel session. action=start begins streaming capture (optional `format` webm/opus, default webm). action=stop ends the stream and returns base64-encoded audio. action=sample captures a fixed-`duration` window in one call (100-60000ms, default 5000ms). Example: audio_capture({ action: "sample", duration: 3000 }). Audio must be playing for capture to record meaningful data. For MIDI export use export_midi; for runtime diagnostics use diagnostics. Each session has its own recorder, so captures in different sessions do not interfere (#180). |
|
|
319
377
|
|
|
320
378
|
</details>
|
|
321
379
|
|
|
@@ -323,11 +381,19 @@ Then ask Claude:
|
|
|
323
381
|
|
|
324
382
|
| Tool | Description |
|
|
325
383
|
|------|-------------|
|
|
326
|
-
| `diagnostics` | Inspect server and browser state.
|
|
384
|
+
| `diagnostics` | Inspect server and browser state. level=status returns a quick state snapshot (cache read, <15ms SLA), plus which config.json was read and any warnings from it. level=full returns detailed browser diagnostics including caches, errors, and performance. level=perf returns server-side timing metrics + top bottlenecks. level=memory returns process memory usage. level=errors returns captured console errors and warnings from Strudel. Default level=full preserves the pre-consolidation behaviour. Example: diagnostics({ level: "status" }) — millisecond-cheap. For screenshots use browser_window; for tool listings use the strudel://docs/tools resource. |
|
|
327
385
|
|
|
328
386
|
</details>
|
|
329
387
|
|
|
330
|
-
|
|
388
|
+
<details><summary><strong>Other</strong> (1)</summary>
|
|
389
|
+
|
|
390
|
+
| Tool | Description |
|
|
391
|
+
|------|-------------|
|
|
392
|
+
| `export_audio` | Record a window of live Strudel audio and write it to a file. Returns a path plus what was actually recorded, not a wall of base64 — prefer this over audio_capture when you want the audio to exist somewhere. format=wav (default) decodes to 16-bit PCM a DAW will open; format=webm writes the raw Opus recording. Reports silent captures instead of writing a silent file and claiming success. Audio must already be playing: call playback({ action: "play" }) first. Example: export_audio({ duration: 4000, filename: "take-01" }). |
|
|
393
|
+
|
|
394
|
+
</details>
|
|
395
|
+
|
|
396
|
+
_Auto-generated from source. 28 tools registered._
|
|
331
397
|
|
|
332
398
|
<!-- TOOLS:END -->
|
|
333
399
|
|
|
@@ -344,7 +410,7 @@ Claude: [Initializes browser]
|
|
|
344
410
|
[Starts playback]
|
|
345
411
|
|
|
346
412
|
Pattern created:
|
|
347
|
-
setcpm(130)
|
|
413
|
+
setcpm(130/4)
|
|
348
414
|
stack(
|
|
349
415
|
s("bd*4"),
|
|
350
416
|
s("~ cp ~ cp"),
|
|
@@ -384,7 +450,7 @@ You: Generate a complete drum & bass track at 174 BPM
|
|
|
384
450
|
Claude: [Creates multi-layer pattern with drums, bass, and pads]
|
|
385
451
|
|
|
386
452
|
// dnb pattern in C at 174 BPM
|
|
387
|
-
setcpm(174)
|
|
453
|
+
setcpm(174/4)
|
|
388
454
|
stack(
|
|
389
455
|
// Drums
|
|
390
456
|
s("bd ~ ~ [bd bd] ~ ~ bd ~, ~ ~ cp ~ ~ cp ~ ~").fast(2),
|
|
@@ -439,7 +505,7 @@ You: Create an ambient soundscape with multiple layers
|
|
|
439
505
|
|
|
440
506
|
Claude: [Generates complex multi-layer pattern]
|
|
441
507
|
|
|
442
|
-
setcpm(90)
|
|
508
|
+
setcpm(90/4)
|
|
443
509
|
stack(
|
|
444
510
|
// Deep bass drone
|
|
445
511
|
note("c1").s("sine").attack(4).release(8).gain(0.5),
|
|
@@ -535,7 +601,7 @@ note("c4 eb4 g4 bb4 c5").struct("1 1 1 1 1 1 1 1")
|
|
|
535
601
|
|
|
536
602
|
## Testing
|
|
537
603
|
|
|
538
|
-
|
|
604
|
+
Tools are exercised against real Strudel.cc interaction through the browser test suite; those are skipped in CI (require Playwright + audio) but run locally:
|
|
539
605
|
|
|
540
606
|
```bash
|
|
541
607
|
# Run integration tests
|
|
@@ -555,273 +621,46 @@ node tests/strudel-integration.js
|
|
|
555
621
|
"headless": false, // Set true for background operation
|
|
556
622
|
"strudel_url": "https://strudel.cc/",
|
|
557
623
|
"patterns_dir": "./patterns",
|
|
624
|
+
"exports_dir": "./exports",
|
|
625
|
+
"viewport": { "width": 1280, "height": 720 }, // or null to track the window size (#514)
|
|
626
|
+
"block_resources": ["image", "font", "media"], // resource types the page route aborts
|
|
558
627
|
"audio_analysis": {
|
|
559
|
-
"fft_size": 2048,
|
|
560
|
-
"smoothing": 0.8
|
|
628
|
+
"fft_size": 2048, // power of 2 in [32, 32768]; code default is 1024
|
|
629
|
+
"smoothing": 0.8 // number in [0, 1]; default 0.8
|
|
561
630
|
}
|
|
562
631
|
}
|
|
563
632
|
```
|
|
564
633
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
The Strudel MCP Server is built with a modular architecture that separates concerns and enables robust music generation:
|
|
570
|
-
|
|
571
|
-
```
|
|
572
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
573
|
-
│ Claude AI │
|
|
574
|
-
│ (MCP Client) │
|
|
575
|
-
└───────────────────────┬─────────────────────────────────────┘
|
|
576
|
-
│ MCP Protocol (stdio)
|
|
577
|
-
│
|
|
578
|
-
┌───────────────────────▼─────────────────────────────────────┐
|
|
579
|
-
│ StrudelMCPServer │
|
|
580
|
-
│ ┌────────────────────────────────────────────────────────┐ │
|
|
581
|
-
│ │ Tool Request Handler │ │
|
|
582
|
-
│ │ - Validates inputs │ │
|
|
583
|
-
│ │ - Routes to appropriate service │ │
|
|
584
|
-
│ │ - Handles errors gracefully │ │
|
|
585
|
-
│ └────────────────────────────────────────────────────────┘ │
|
|
586
|
-
└───────┬────────────┬────────────┬───────────┬──────────────┘
|
|
587
|
-
│ │ │ │
|
|
588
|
-
┌────▼────┐ ┌───▼────┐ ┌───▼────┐ ┌──▼──────┐
|
|
589
|
-
│ Strudel │ │ Music │ │Pattern │ │ Pattern │
|
|
590
|
-
│Controller│ │ Theory │ │Generator│ │ Store │
|
|
591
|
-
└────┬────┘ └────────┘ └────────┘ └─────────┘
|
|
592
|
-
│
|
|
593
|
-
┌────▼────────────────────────────┐
|
|
594
|
-
│ Playwright Browser │
|
|
595
|
-
│ ┌──────────────────────────┐ │
|
|
596
|
-
│ │ Strudel.cc Website │ │
|
|
597
|
-
│ │ ┌────────────────────┐ │ │
|
|
598
|
-
│ │ │ CodeMirror Editor │ │ │
|
|
599
|
-
│ │ └────────────────────┘ │ │
|
|
600
|
-
│ │ ┌────────────────────┐ │ │
|
|
601
|
-
│ │ │ Audio Context │ │ │
|
|
602
|
-
│ │ │ + Web Audio API │ │ │
|
|
603
|
-
│ │ └────────┬───────────┘ │ │
|
|
604
|
-
│ └───────────┼──────────────┘ │
|
|
605
|
-
└──────────────┼──────────────────┘
|
|
606
|
-
│
|
|
607
|
-
┌───────▼────────┐
|
|
608
|
-
│ Audio Analyzer │
|
|
609
|
-
│ - FFT Analysis│
|
|
610
|
-
│ - Frequency │
|
|
611
|
-
│ - Spectral │
|
|
612
|
-
└────────────────┘
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
### Core Components
|
|
616
|
-
|
|
617
|
-
#### 1. **StrudelMCPServer** (`src/server/server.ts`, ~510 lines)
|
|
618
|
-
|
|
619
|
-
Thin MCP dispatcher that:
|
|
620
|
-
- Aggregates 26 tool definitions from the per-domain modules in `src/server/tools/`
|
|
621
|
-
- Routes `tools/call` requests to the right module's `execute()`
|
|
622
|
-
- Wraps every response in the discriminated result envelope (`{ ok, errorCategory, isRetryable, ... }`)
|
|
623
|
-
- Tracks initialization, per-session history bundles, per-session audio capture services
|
|
624
|
-
- Advertises and serves MCP resources (`strudel://examples`, etc.)
|
|
625
|
-
- Lazy-initializes the default browser controller on first browser-touching call
|
|
626
|
-
|
|
627
|
-
Key Features:
|
|
628
|
-
```typescript
|
|
629
|
-
- Pattern caching before browser init
|
|
630
|
-
- Undo/redo stack management
|
|
631
|
-
- Session history tracking
|
|
632
|
-
- Generated pattern storage
|
|
633
|
-
- Safe fallback mechanisms
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
#### 2. **StrudelController** (`src/StrudelController.ts`)
|
|
637
|
-
|
|
638
|
-
Browser automation layer using Playwright:
|
|
639
|
-
- **Browser Management**: Chromium instance lifecycle
|
|
640
|
-
- **Editor Control**: CodeMirror manipulation via DOM
|
|
641
|
-
- **Playback Control**: Keyboard shortcuts for play/stop
|
|
642
|
-
- **Performance Optimizations**:
|
|
643
|
-
- Editor content caching (100ms TTL)
|
|
644
|
-
- Direct CodeMirror API access
|
|
645
|
-
- Resource blocking (images, fonts)
|
|
646
|
-
- Fast DOM content loading
|
|
647
|
-
|
|
648
|
-
```typescript
|
|
649
|
-
// Example: Optimized pattern writing
|
|
650
|
-
async writePattern(pattern: string) {
|
|
651
|
-
await this.page.evaluate((newPattern) => {
|
|
652
|
-
const editor = document.querySelector('.cm-content');
|
|
653
|
-
const view = editor.__view;
|
|
654
|
-
view.dispatch({
|
|
655
|
-
changes: { from: 0, to: view.state.doc.length, insert: newPattern }
|
|
656
|
-
});
|
|
657
|
-
}, pattern);
|
|
658
|
-
}
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
#### 3. **AudioAnalyzer** (`src/AudioAnalyzer.ts`)
|
|
662
|
-
|
|
663
|
-
Real-time audio analysis via Web Audio API injection:
|
|
664
|
-
- **FFT Analysis**: 1024-point FFT for spectral data
|
|
665
|
-
- **Frequency Bands**: Bass, low-mid, mid, high-mid, treble
|
|
666
|
-
- **Analysis Caching**: 50ms TTL for performance
|
|
667
|
-
- **Features Extracted**:
|
|
668
|
-
- Average amplitude
|
|
669
|
-
- Peak frequency
|
|
670
|
-
- Spectral centroid
|
|
671
|
-
- Playing state detection
|
|
672
|
-
- Frequency distribution
|
|
673
|
-
|
|
674
|
-
```typescript
|
|
675
|
-
Features provided:
|
|
676
|
-
- average: Overall amplitude (0-255)
|
|
677
|
-
- peak: Maximum amplitude
|
|
678
|
-
- peakFrequency: Dominant frequency in Hz
|
|
679
|
-
- bass/mid/treble: Band-specific amplitudes
|
|
680
|
-
- brightness: Timbral classification
|
|
681
|
-
- isPlaying: Boolean playback state
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
#### 4. **MusicTheory** (`src/services/MusicTheory.ts`)
|
|
685
|
-
|
|
686
|
-
Music theory engine providing:
|
|
687
|
-
- **15+ Scales**: Major, minor, modes, pentatonic, blues, whole-tone
|
|
688
|
-
- **Chord Progressions**: Pop, jazz, blues, rock, folk, EDM
|
|
689
|
-
- **Euclidean Rhythms**: Mathematical rhythm generation
|
|
690
|
-
- **Arpeggio Generation**: Multiple patterns (up, down, random)
|
|
691
|
-
- **Note Transposition**: Semitone-based pitch shifting
|
|
692
|
-
|
|
693
|
-
Supported scales:
|
|
694
|
-
```typescript
|
|
695
|
-
major, minor, dorian, phrygian, lydian, mixolydian,
|
|
696
|
-
aeolian, locrian, pentatonic, blues, chromatic,
|
|
697
|
-
wholetone, harmonic_minor, melodic_minor
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
#### 5. **PatternGenerator** (`src/services/PatternGenerator.ts`)
|
|
634
|
+
`strudel_url` is the REPL the browser is pointed at — set it to run against a self-hosted or
|
|
635
|
+
pinned Strudel build. Only `http`/`https` are accepted; anything else falls back to the default
|
|
636
|
+
with a logged warning. `patterns_dir` is where `pattern_store` reads and writes.
|
|
701
637
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
- **Fills**: 1-4 bar drum fills
|
|
638
|
+
`viewport` pins the Playwright page layout. Set it to `null` in a headed window so dragging the
|
|
639
|
+
window resizes the page and strudel's canvases follow (#514). `block_resources` lists the
|
|
640
|
+
resource types the page route aborts to speed up load; the default blocks `image`, `font`, and
|
|
641
|
+
`media`, which suits headless CI but degrades the live editor (fallback-font button metrics,
|
|
642
|
+
canvases that ignore window resizes). A live-coding setup wants `"block_resources": ["media"]`.
|
|
643
|
+
Both keys fall back to the defaults with a logged warning when invalid.
|
|
709
644
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
→ Multi-layer pattern with drums, bass, chords, melody
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
#### 6. **PatternStore** (`src/PatternStore.ts`)
|
|
717
|
-
|
|
718
|
-
Persistent pattern storage:
|
|
719
|
-
- **JSON-based**: Simple file storage
|
|
720
|
-
- **Metadata**: Name, tags, timestamp, audio features
|
|
721
|
-
- **Tag Filtering**: Organize by genre, mood, project
|
|
722
|
-
- **Sorted Retrieval**: Most recent first
|
|
723
|
-
|
|
724
|
-
### Directory Structure
|
|
725
|
-
|
|
726
|
-
```
|
|
727
|
-
live-coding-music-mcp/
|
|
728
|
-
├── src/
|
|
729
|
-
│ ├── server/
|
|
730
|
-
│ │ ├── server.ts # MCP dispatcher (~510 lines)
|
|
731
|
-
│ │ ├── resources.ts # MCP resources (#131)
|
|
732
|
-
│ │ └── tools/
|
|
733
|
-
│ │ ├── ai.ts, analysis.ts, capture.ts, compose.ts,
|
|
734
|
-
│ │ ├── diagnostics.ts, editor.ts, generate.ts, history.ts,
|
|
735
|
-
│ │ ├── playback.ts, session.ts, storage.ts, transform.ts,
|
|
736
|
-
│ │ └── types.ts # ToolContext, Envelope, helpers
|
|
737
|
-
│ ├── services/
|
|
738
|
-
│ │ ├── MusicTheory.ts # Scale/chord/euclidean helpers
|
|
739
|
-
│ │ ├── PatternGenerator.ts # Template-based generation
|
|
740
|
-
│ │ ├── SessionManager.ts # Multi-session lifecycle (#108)
|
|
741
|
-
│ │ ├── AudioCaptureService.ts # Audio recording
|
|
742
|
-
│ │ ├── MIDIExportService.ts # MIDI export
|
|
743
|
-
│ │ ├── GeminiService.ts # Gemini API client (ai_assist)
|
|
744
|
-
│ │ ├── StrudelEngine.ts # @strudel/* wrapper
|
|
745
|
-
│ │ └── StrudelEngineHelpers.ts # Pure helpers (#107)
|
|
746
|
-
│ ├── utils/
|
|
747
|
-
│ │ ├── Logger.ts
|
|
748
|
-
│ │ ├── PatternValidator.ts # Syntax + safety checks
|
|
749
|
-
│ │ ├── ErrorRecovery.ts # Retry / backoff
|
|
750
|
-
│ │ ├── PerformanceMonitor.ts
|
|
751
|
-
│ │ └── InputValidator.ts # Input bound checks
|
|
752
|
-
│ ├── StrudelController.ts # Browser automation (~800 lines)
|
|
753
|
-
│ ├── AudioAnalyzer.ts # Audio analysis (~800 lines)
|
|
754
|
-
│ ├── PatternStore.ts # On-disk pattern persistence
|
|
755
|
-
│ └── index.ts # Entry point
|
|
756
|
-
├── src/__tests__/ # Jest suites (unit + integration + browser)
|
|
757
|
-
├── patterns/
|
|
758
|
-
│ ├── examples/ # 18 bundled example patterns
|
|
759
|
-
│ └── *.json # Saved patterns at runtime
|
|
760
|
-
├── scripts/
|
|
761
|
-
│ ├── generate-tool-docs.ts # README tool-table generator
|
|
762
|
-
│ └── generate-changelog.ts
|
|
763
|
-
├── config.json # Local config (gitignored)
|
|
764
|
-
├── package.json
|
|
765
|
-
└── tsconfig.json
|
|
766
|
-
```
|
|
767
|
-
|
|
768
|
-
### Data Flow
|
|
769
|
-
|
|
770
|
-
1. **Tool Invocation**
|
|
771
|
-
```
|
|
772
|
-
Claude → MCP Protocol → StrudelMCPServer
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
2. **Pattern Generation** (without browser)
|
|
776
|
-
```
|
|
777
|
-
Server → PatternGenerator → MusicTheory → Pattern String
|
|
778
|
-
```
|
|
645
|
+
`exports_dir` is where `export_midi({format:"file"})` writes. Exported filenames are reduced to a
|
|
646
|
+
basename and confined to this directory — a name containing path separators is sanitized rather
|
|
647
|
+
than honoured, and the response reports the path actually written.
|
|
779
648
|
|
|
780
|
-
|
|
781
|
-
```
|
|
782
|
-
Server → StrudelController → Playwright → Strudel.cc
|
|
783
|
-
```
|
|
649
|
+
Unknown top-level keys are logged as warnings at startup rather than silently ignored.
|
|
784
650
|
|
|
785
|
-
|
|
786
|
-
```
|
|
787
|
-
Strudel.cc → Web Audio API → AudioAnalyzer → Feature Data
|
|
788
|
-
```
|
|
789
|
-
|
|
790
|
-
### Performance Characteristics
|
|
791
|
-
|
|
792
|
-
| Operation | Latency | Notes |
|
|
793
|
-
|-----------|---------|-------|
|
|
794
|
-
| Pattern Generation | <100ms | Pure computation |
|
|
795
|
-
| Browser Init | ~3s | One-time cost |
|
|
796
|
-
| Pattern Write | ~50ms | With caching |
|
|
797
|
-
| Play/Stop | ~100ms | Keyboard shortcuts |
|
|
798
|
-
| Audio Analysis | ~20ms | With 50ms cache |
|
|
799
|
-
| Pattern Save | ~10ms | File I/O |
|
|
800
|
-
|
|
801
|
-
### Optimization Strategies
|
|
802
|
-
|
|
803
|
-
1. **Caching**
|
|
804
|
-
- Editor content: 100ms TTL
|
|
805
|
-
- Audio analysis: 50ms TTL
|
|
806
|
-
- Generated patterns: Until browser init
|
|
651
|
+
`audio_analysis.fft_size` tunes the FFT bin count on the `AnalyserNode` attached to Strudel's audio graph — larger = better frequency resolution at higher CPU cost. `smoothing` is the analyser's `smoothingTimeConstant` (higher = steadier spectrum, more lag). Invalid values fall back to defaults with a warning; the frequency-band boundaries inside `analyze` rescale automatically so band Hz coverage stays consistent across FFT sizes.
|
|
807
652
|
|
|
808
|
-
|
|
809
|
-
- Images, fonts, media blocked
|
|
810
|
-
- Only load essential JavaScript/CSS
|
|
653
|
+
## Architecture
|
|
811
654
|
|
|
812
|
-
|
|
813
|
-
- CodeMirror view manipulation
|
|
814
|
-
- Keyboard shortcuts over button clicks
|
|
655
|
+
The server is a thin MCP dispatcher (`src/server/server.ts`, ~520 lines) over twelve per-domain tool modules (`src/server/tools/*.ts`), ten services (MusicTheory, PatternGenerator, SessionManager, AudioCaptureService, AudioExportService, GeminiService, MIDIExportService, MIDIImportService, StrudelEngine, PatternSandbox) plus a provider-agnostic AI transport layer (`src/services/ai/`), two controllers (StrudelController for Playwright, AudioAnalyzer for Web Audio API), and a JSON-on-disk PatternStore. Browser automation drives the editor on strudel.cc through `window.strudelMirror.editor.dispatch(...)` rather than keyboard simulation — about 80% faster.
|
|
815
656
|
|
|
816
|
-
|
|
817
|
-
- Browser starts only when needed
|
|
818
|
-
- Services initialized on-demand
|
|
657
|
+
For the full breakdown — component diagram, per-component responsibilities, directory layout, data flow, and optimization strategies — see **[ARCHITECTURE.md](ARCHITECTURE.md)**.
|
|
819
658
|
|
|
820
659
|
## Pattern Examples
|
|
821
660
|
|
|
822
661
|
### Minimal Techno (Verified Working)
|
|
823
662
|
```javascript
|
|
824
|
-
setcpm(130)
|
|
663
|
+
setcpm(130/4)
|
|
825
664
|
stack(
|
|
826
665
|
s("bd*4").gain(0.9),
|
|
827
666
|
s("~ cp ~ cp").room(0.2),
|
|
@@ -832,7 +671,7 @@ stack(
|
|
|
832
671
|
|
|
833
672
|
### Drum & Bass (Verified Working)
|
|
834
673
|
```javascript
|
|
835
|
-
setcpm(174)
|
|
674
|
+
setcpm(174/4)
|
|
836
675
|
stack(
|
|
837
676
|
s("bd ~ ~ [bd bd] ~ ~ bd ~, ~ ~ sn:3 ~ ~ sn:3 ~ ~").fast(2),
|
|
838
677
|
s("hh*16").gain(0.5),
|
|
@@ -864,347 +703,15 @@ docker-compose up
|
|
|
864
703
|
|
|
865
704
|
## Development
|
|
866
705
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
```bash
|
|
870
|
-
# Clone the repository
|
|
871
|
-
git clone https://github.com/williamzujkowski/live-coding-music-mcp.git
|
|
872
|
-
cd live-coding-music-mcp
|
|
873
|
-
|
|
874
|
-
# Install dependencies
|
|
875
|
-
npm install
|
|
876
|
-
|
|
877
|
-
# Install Playwright browsers
|
|
878
|
-
npx playwright install chromium
|
|
879
|
-
|
|
880
|
-
# Build the project
|
|
881
|
-
npm run build
|
|
882
|
-
```
|
|
883
|
-
|
|
884
|
-
### Available Scripts
|
|
706
|
+
For development setup, scripts, debugging, adding new tools, and the release process, see **[DEVELOPMENT.md](DEVELOPMENT.md)**.
|
|
885
707
|
|
|
886
|
-
|
|
887
|
-
#
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
#
|
|
891
|
-
npm run build
|
|
892
|
-
|
|
893
|
-
# Start production server
|
|
894
|
-
npm start
|
|
895
|
-
|
|
896
|
-
# Run all tests
|
|
897
|
-
npm test
|
|
898
|
-
|
|
899
|
-
# Run integration tests with real browser
|
|
900
|
-
npm run test:integration
|
|
901
|
-
|
|
902
|
-
# Run browser-specific tests
|
|
903
|
-
npm run test:browser
|
|
904
|
-
|
|
905
|
-
# Validate MCP protocol compliance
|
|
906
|
-
npm run validate
|
|
907
|
-
|
|
908
|
-
# Lint code
|
|
909
|
-
npm run lint
|
|
910
|
-
|
|
911
|
-
# Format code
|
|
912
|
-
npm run format
|
|
913
|
-
|
|
914
|
-
# Clean build artifacts
|
|
915
|
-
npm clean
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
### Publishing to npm
|
|
919
|
-
|
|
920
|
-
See [NPM_PUBLISHING.md](NPM_PUBLISHING.md) for complete publishing instructions.
|
|
921
|
-
|
|
922
|
-
**Quick publish via GitHub Release:**
|
|
923
|
-
```bash
|
|
924
|
-
npm version patch # or minor, major
|
|
925
|
-
git push && git push --tags
|
|
926
|
-
gh release create v$(node -p "require('./package.json').version") --generate-notes
|
|
927
|
-
```
|
|
928
|
-
|
|
929
|
-
The package uses OIDC trusted publishing with provenance attestation for supply chain security.
|
|
930
|
-
|
|
931
|
-
### Adding new tools
|
|
932
|
-
|
|
933
|
-
Tools live in per-domain modules under `src/server/tools/<domain>.ts`. `server.ts` just dispatches. To add a tool:
|
|
934
|
-
|
|
935
|
-
1. **Pick the right domain module** (or add a new one). Add the tool definition to that module's `tools` array:
|
|
936
|
-
|
|
937
|
-
```typescript
|
|
938
|
-
export const tools: Tool[] = [
|
|
939
|
-
// ...
|
|
940
|
-
{
|
|
941
|
-
name: 'my_new_tool',
|
|
942
|
-
description: 'One-line description; agents read this to pick between adjacent tools',
|
|
943
|
-
inputSchema: {
|
|
944
|
-
type: 'object',
|
|
945
|
-
properties: {
|
|
946
|
-
param1: { type: 'string', description: 'What it is' },
|
|
947
|
-
session_id: { type: 'string', description: 'Optional session ID (#108)' },
|
|
948
|
-
},
|
|
949
|
-
required: ['param1'],
|
|
950
|
-
},
|
|
951
|
-
},
|
|
952
|
-
];
|
|
953
|
-
```
|
|
954
|
-
|
|
955
|
-
2. **Add the case** to the module's `execute()` switch:
|
|
956
|
-
|
|
957
|
-
```typescript
|
|
958
|
-
case 'my_new_tool':
|
|
959
|
-
return await ctx.getController(args.session_id).doSomething(args.param1);
|
|
960
|
-
```
|
|
961
|
-
|
|
962
|
-
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.
|
|
963
|
-
|
|
964
|
-
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.
|
|
965
|
-
|
|
966
|
-
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.
|
|
967
|
-
|
|
968
|
-
6. **Build and test**:
|
|
969
|
-
|
|
970
|
-
```bash
|
|
971
|
-
npm run build
|
|
972
|
-
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"my_new_tool","arguments":{"param1":"test"}},"id":2}' | node dist/index.js
|
|
973
|
-
```
|
|
974
|
-
|
|
975
|
-
### Testing Strategy
|
|
976
|
-
|
|
977
|
-
#### 1. Unit Tests
|
|
978
|
-
```bash
|
|
979
|
-
# Run with Jest
|
|
980
|
-
npm test
|
|
981
|
-
|
|
982
|
-
# Watch mode
|
|
983
|
-
npm run test:watch
|
|
984
|
-
```
|
|
985
|
-
|
|
986
|
-
#### 2. Integration Tests
|
|
987
|
-
```bash
|
|
988
|
-
# Full integration with real browser
|
|
989
|
-
npm run test:integration
|
|
990
|
-
|
|
991
|
-
# This tests:
|
|
992
|
-
# - Browser initialization
|
|
993
|
-
# - Pattern generation
|
|
994
|
-
# - Audio analysis
|
|
995
|
-
# - Pattern storage
|
|
996
|
-
# - All 84 registered tools
|
|
997
|
-
```
|
|
998
|
-
|
|
999
|
-
#### 3. Manual Testing
|
|
1000
|
-
```bash
|
|
1001
|
-
# Development mode
|
|
1002
|
-
npm run dev
|
|
1003
|
-
|
|
1004
|
-
# In another terminal
|
|
1005
|
-
claude mcp add strudel-dev node $(pwd)/dist/index.js
|
|
1006
|
-
claude chat
|
|
1007
|
-
|
|
1008
|
-
# Then interact with Claude
|
|
1009
|
-
```
|
|
1010
|
-
|
|
1011
|
-
### Code Quality
|
|
1012
|
-
|
|
1013
|
-
**TypeScript Configuration**
|
|
1014
|
-
```json
|
|
1015
|
-
// tsconfig.json
|
|
1016
|
-
{
|
|
1017
|
-
"compilerOptions": {
|
|
1018
|
-
"strict": true, // Strict type checking
|
|
1019
|
-
"esModuleInterop": true, // Better module compatibility
|
|
1020
|
-
"target": "ES2020", // Modern JavaScript
|
|
1021
|
-
"module": "ES2020", // ES modules
|
|
1022
|
-
"moduleResolution": "node"
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
```
|
|
1026
|
-
|
|
1027
|
-
**Linting & Formatting**
|
|
1028
|
-
```bash
|
|
1029
|
-
# ESLint
|
|
1030
|
-
npm run lint
|
|
1031
|
-
|
|
1032
|
-
# Prettier
|
|
1033
|
-
npm run format
|
|
1034
|
-
|
|
1035
|
-
# Pre-commit hooks recommended
|
|
1036
|
-
```
|
|
1037
|
-
|
|
1038
|
-
### Debugging
|
|
1039
|
-
|
|
1040
|
-
**Enable Debug Logging**
|
|
1041
|
-
```bash
|
|
1042
|
-
# Set DEBUG environment variable
|
|
1043
|
-
DEBUG=strudel:* npm start
|
|
1044
|
-
|
|
1045
|
-
# Or specific modules
|
|
1046
|
-
DEBUG=strudel:controller npm start
|
|
1047
|
-
DEBUG=strudel:audio npm start
|
|
1048
|
-
```
|
|
1049
|
-
|
|
1050
|
-
**VS Code Launch Configuration**
|
|
1051
|
-
```json
|
|
1052
|
-
{
|
|
1053
|
-
"type": "node",
|
|
1054
|
-
"request": "launch",
|
|
1055
|
-
"name": "Debug MCP Server",
|
|
1056
|
-
"program": "${workspaceFolder}/dist/index.js",
|
|
1057
|
-
"preLaunchTask": "npm: build",
|
|
1058
|
-
"console": "integratedTerminal",
|
|
1059
|
-
"env": {
|
|
1060
|
-
"DEBUG": "strudel:*"
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
```
|
|
1064
|
-
|
|
1065
|
-
**Playwright Debugging**
|
|
1066
|
-
```typescript
|
|
1067
|
-
// In StrudelController.ts
|
|
1068
|
-
this.browser = await chromium.launch({
|
|
1069
|
-
headless: false, // See the browser
|
|
1070
|
-
devtools: true, // Open DevTools
|
|
1071
|
-
slowMo: 100 // Slow down actions
|
|
1072
|
-
});
|
|
1073
|
-
```
|
|
1074
|
-
|
|
1075
|
-
### Performance Monitoring
|
|
1076
|
-
|
|
1077
|
-
The server includes built-in performance monitoring:
|
|
1078
|
-
|
|
1079
|
-
```typescript
|
|
1080
|
-
// Access performance metrics
|
|
1081
|
-
You: Show me performance metrics
|
|
1082
|
-
|
|
1083
|
-
Claude: Performance Report:
|
|
1084
|
-
{
|
|
1085
|
-
"averageLatency": {
|
|
1086
|
-
"init": "3.2s",
|
|
1087
|
-
"write": "52ms",
|
|
1088
|
-
"play": "105ms",
|
|
1089
|
-
"analyze": "18ms"
|
|
1090
|
-
},
|
|
1091
|
-
"cacheHitRate": "85%",
|
|
1092
|
-
"totalOperations": 1247,
|
|
1093
|
-
"bottlenecks": [
|
|
1094
|
-
{"tool": "init", "avgTime": 3200, "calls": 1},
|
|
1095
|
-
{"tool": "write", "avgTime": 52, "calls": 156}
|
|
1096
|
-
]
|
|
1097
|
-
}
|
|
1098
|
-
```
|
|
1099
|
-
|
|
1100
|
-
### Contributing Guidelines
|
|
1101
|
-
|
|
1102
|
-
1. **Fork the repository**
|
|
1103
|
-
```bash
|
|
1104
|
-
git clone https://github.com/YOUR_USERNAME/live-coding-music-mcp.git
|
|
1105
|
-
```
|
|
1106
|
-
|
|
1107
|
-
2. **Create a feature branch**
|
|
1108
|
-
```bash
|
|
1109
|
-
git checkout -b feature/my-new-feature
|
|
1110
|
-
```
|
|
1111
|
-
|
|
1112
|
-
3. **Make your changes**
|
|
1113
|
-
- Follow existing code style
|
|
1114
|
-
- Add tests for new features
|
|
1115
|
-
- Update documentation
|
|
1116
|
-
- Ensure all tests pass
|
|
1117
|
-
|
|
1118
|
-
4. **Commit with meaningful messages**
|
|
1119
|
-
```bash
|
|
1120
|
-
git commit -m "feat: Add support for custom scale generation"
|
|
1121
|
-
```
|
|
1122
|
-
|
|
1123
|
-
Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
1124
|
-
- `feat:` New feature
|
|
1125
|
-
- `fix:` Bug fix
|
|
1126
|
-
- `docs:` Documentation changes
|
|
1127
|
-
- `refactor:` Code refactoring
|
|
1128
|
-
- `test:` Adding tests
|
|
1129
|
-
- `chore:` Maintenance tasks
|
|
1130
|
-
|
|
1131
|
-
5. **Push and create PR**
|
|
1132
|
-
```bash
|
|
1133
|
-
git push origin feature/my-new-feature
|
|
1134
|
-
```
|
|
1135
|
-
|
|
1136
|
-
Then create a Pull Request on GitHub with:
|
|
1137
|
-
- Clear description of changes
|
|
1138
|
-
- Link to related issues
|
|
1139
|
-
- Screenshots/examples if relevant
|
|
1140
|
-
|
|
1141
|
-
### Release Process
|
|
708
|
+
Quick links:
|
|
709
|
+
- [Setup](DEVELOPMENT.md#setup) — `git clone` to `npm test`
|
|
710
|
+
- [Adding new tools](DEVELOPMENT.md#adding-new-tools) — module pattern + envelope helpers
|
|
711
|
+
- [Release process](DEVELOPMENT.md#release-process) — `gh release create` triggers the publish workflow
|
|
712
|
+
- [Contributing](DEVELOPMENT.md#contributing) — commit conventions and PR flow
|
|
1142
713
|
|
|
1143
|
-
|
|
1144
|
-
# 1. Update version in package.json
|
|
1145
|
-
npm version patch # or minor/major
|
|
1146
|
-
|
|
1147
|
-
# 2. Update CHANGELOG.md
|
|
1148
|
-
# Add entry for new version
|
|
1149
|
-
|
|
1150
|
-
# 3. Build and test
|
|
1151
|
-
npm run build
|
|
1152
|
-
npm test
|
|
1153
|
-
npm run test:integration
|
|
1154
|
-
|
|
1155
|
-
# 4. Commit version bump
|
|
1156
|
-
git add .
|
|
1157
|
-
git commit -m "chore: Bump version to X.Y.Z"
|
|
1158
|
-
|
|
1159
|
-
# 5. Create git tag
|
|
1160
|
-
git tag vX.Y.Z
|
|
1161
|
-
|
|
1162
|
-
# 6. Push to GitHub
|
|
1163
|
-
git push origin main --tags
|
|
1164
|
-
|
|
1165
|
-
# 7. Publish to npm (if you have access)
|
|
1166
|
-
npm publish --access public
|
|
1167
|
-
|
|
1168
|
-
# 8. Create GitHub release
|
|
1169
|
-
gh release create vX.Y.Z --generate-notes
|
|
1170
|
-
```
|
|
1171
|
-
|
|
1172
|
-
### Docker Development
|
|
1173
|
-
|
|
1174
|
-
```bash
|
|
1175
|
-
# Build development image
|
|
1176
|
-
docker build -t live-coding-music-mcp:dev .
|
|
1177
|
-
|
|
1178
|
-
# Run with volume mount for hot reload
|
|
1179
|
-
docker run -it --rm \
|
|
1180
|
-
-v $(pwd)/src:/app/src \
|
|
1181
|
-
-v $(pwd)/patterns:/app/patterns \
|
|
1182
|
-
live-coding-music-mcp:dev
|
|
1183
|
-
|
|
1184
|
-
# Run tests in container
|
|
1185
|
-
docker run -it --rm live-coding-music-mcp:dev npm test
|
|
1186
|
-
```
|
|
1187
|
-
|
|
1188
|
-
### Environment Variables
|
|
1189
|
-
|
|
1190
|
-
```bash
|
|
1191
|
-
# Logging level
|
|
1192
|
-
LOG_LEVEL=debug # debug, info, warn, error
|
|
1193
|
-
|
|
1194
|
-
# Performance monitoring
|
|
1195
|
-
ENABLE_PERF_MONITORING=true
|
|
1196
|
-
|
|
1197
|
-
# Pattern storage
|
|
1198
|
-
PATTERNS_DIR=./patterns
|
|
1199
|
-
|
|
1200
|
-
# Browser configuration
|
|
1201
|
-
HEADLESS=false
|
|
1202
|
-
BROWSER_TIMEOUT=15000
|
|
1203
|
-
|
|
1204
|
-
# Audio analysis
|
|
1205
|
-
FFT_SIZE=1024
|
|
1206
|
-
SMOOTHING=0.8
|
|
1207
|
-
```
|
|
714
|
+
The [Configuration](#configuration) section above covers runtime config (`config.json`). [ARCHITECTURE.md](ARCHITECTURE.md) covers the system design.
|
|
1208
715
|
|
|
1209
716
|
## Performance
|
|
1210
717
|
|
|
@@ -1217,8 +724,8 @@ Measured against the current `StrudelController` cache + Strudel.cc on a develop
|
|
|
1217
724
|
| Pattern read (cached) | 10–15 ms |
|
|
1218
725
|
| Play / pause / stop | 100–150 ms |
|
|
1219
726
|
| Audio analysis (single FFT) | 10–15 ms |
|
|
1220
|
-
| Tempo detection | <100 ms (onset-based;
|
|
1221
|
-
| Key detection | <100 ms (Krumhansl-Schmuckler) |
|
|
727
|
+
| Tempo detection | <100 ms (onset-based; reports poll cadence, not tempo — #322) |
|
|
728
|
+
| Key detection | <100 ms (Krumhansl-Schmuckler, Pearson; bass-register accuracy depends on `fft_size`) |
|
|
1222
729
|
| Pattern generation | <100 ms (template-based) |
|
|
1223
730
|
| Process resident memory | ~120–150 MB |
|
|
1224
731
|
|
|
@@ -1389,7 +896,7 @@ s("bd*4")
|
|
|
1389
896
|
.every(8, x => x.sometimes(y => y.fast(2)))
|
|
1390
897
|
```
|
|
1391
898
|
|
|
1392
|
-
##
|
|
899
|
+
## Security
|
|
1393
900
|
|
|
1394
901
|
### Pattern Validation
|
|
1395
902
|
|
|
@@ -1398,11 +905,23 @@ All patterns are validated before execution:
|
|
|
1398
905
|
- **Eval blocks** are rejected
|
|
1399
906
|
- **Path traversal** attacks are blocked in PatternStore
|
|
1400
907
|
|
|
1401
|
-
### Browser
|
|
908
|
+
### Browser Isolation
|
|
909
|
+
|
|
910
|
+
Be precise about what this does and does not give you:
|
|
911
|
+
|
|
912
|
+
- **The OS-level Chrome sandbox is disabled.** Chromium is launched with `--no-sandbox` and
|
|
913
|
+
`--disable-setuid-sandbox` ([`src/StrudelController.ts`](src/StrudelController.ts)) for headless
|
|
914
|
+
and container compatibility, where the sandbox otherwise needs `CAP_SYS_ADMIN` or user namespaces.
|
|
915
|
+
This is a deliberate trade-off, not a security feature.
|
|
916
|
+
- **The browser context is a fresh, non-persistent Playwright context** — no profile on disk, no
|
|
917
|
+
cookies or storage carried over between runs, and no `file://` navigation is ever performed.
|
|
918
|
+
- **Resource blocking is a performance optimization, not a security boundary.** Images, fonts, and
|
|
919
|
+
media are aborted to speed up page load; scripts, stylesheets, and network requests from
|
|
920
|
+
strudel.cc are allowed through as normal.
|
|
921
|
+
- **Patterns are validated before execution** (see above), which is the actual pre-execution control.
|
|
1402
922
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
- Resource blocking prevents loading external content
|
|
923
|
+
If you need real isolation, run the whole MCP server inside a locked-down container or VM. The
|
|
924
|
+
server does not sandbox itself.
|
|
1406
925
|
|
|
1407
926
|
### Known Limitations
|
|
1408
927
|
|
|
@@ -1414,7 +933,7 @@ All patterns are validated before execution:
|
|
|
1414
933
|
|
|
1415
934
|
Found a vulnerability? Please [open a security issue](https://github.com/williamzujkowski/live-coding-music-mcp/security/advisories/new) or email the maintainer directly. Do not disclose publicly until patched.
|
|
1416
935
|
|
|
1417
|
-
##
|
|
936
|
+
## Troubleshooting
|
|
1418
937
|
|
|
1419
938
|
### Common Issues
|
|
1420
939
|
|
|
@@ -1481,7 +1000,7 @@ npm run build
|
|
|
1481
1000
|
# Check if server responds
|
|
1482
1001
|
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js
|
|
1483
1002
|
|
|
1484
|
-
# Should return JSON with
|
|
1003
|
+
# Should return JSON with 28 tools
|
|
1485
1004
|
|
|
1486
1005
|
# Reinstall MCP server in Claude
|
|
1487
1006
|
claude mcp remove strudel
|
|
@@ -1522,7 +1041,7 @@ claude chat
|
|
|
1522
1041
|
- Use resource blocking (enabled by default)
|
|
1523
1042
|
|
|
1524
1043
|
#### Patterns not saving
|
|
1525
|
-
**Symptom**: `save`
|
|
1044
|
+
**Symptom**: `pattern_store({ action: "save" })` fails or patterns don't persist
|
|
1526
1045
|
|
|
1527
1046
|
**Solutions**:
|
|
1528
1047
|
```bash
|
|
@@ -1590,7 +1109,7 @@ Claude: Browser state:
|
|
|
1590
1109
|
- Initialized: true
|
|
1591
1110
|
- Cached patterns: 2
|
|
1592
1111
|
- Undo stack depth: 5
|
|
1593
|
-
- Last operation:
|
|
1112
|
+
- Last operation: edit_pattern (2.5s ago)
|
|
1594
1113
|
```
|
|
1595
1114
|
|
|
1596
1115
|
**Validate Pattern Syntax**
|
|
@@ -1613,50 +1132,28 @@ If you encounter issues not covered here:
|
|
|
1613
1132
|
4. **Consult Strudel docs**: [Strudel.cc documentation](https://strudel.cc/learn)
|
|
1614
1133
|
5. **Create new issue**: Include error messages, OS, Node version, and steps to reproduce
|
|
1615
1134
|
|
|
1616
|
-
##
|
|
1617
|
-
|
|
1618
|
-
**We need your help!** This project is actively developed and welcomes contributions of all kinds:
|
|
1619
|
-
|
|
1620
|
-
### Ways to Contribute
|
|
1621
|
-
- **Report Bugs**: Found an issue? [Open a bug report](https://github.com/williamzujkowski/live-coding-music-mcp/issues/new)
|
|
1622
|
-
- **Suggest Features**: Have ideas? [Create a feature request](https://github.com/williamzujkowski/live-coding-music-mcp/issues/new)
|
|
1623
|
-
- **Improve Docs**: Fix typos, add examples, clarify confusing sections
|
|
1624
|
-
- **Write Tests**: Help us improve test coverage
|
|
1625
|
-
- **Fix Issues**: Check [open issues](https://github.com/williamzujkowski/live-coding-music-mcp/issues) for bugs to fix
|
|
1626
|
-
- **Add Features**: Implement new tools or improve existing ones
|
|
1627
|
-
|
|
1628
|
-
### Quick Start for Contributors
|
|
1629
|
-
1. Fork the repository
|
|
1630
|
-
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
1631
|
-
3. Make your changes and add tests
|
|
1632
|
-
4. Ensure tests pass (`npm test`)
|
|
1633
|
-
5. Commit with clear messages (`git commit -m 'fix: resolve audio analysis bug'`)
|
|
1634
|
-
6. Push to your fork (`git push origin feature/amazing-feature`)
|
|
1635
|
-
7. Open a Pull Request
|
|
1135
|
+
## Contributing
|
|
1636
1136
|
|
|
1637
|
-
|
|
1137
|
+
PRs welcome — bug fixes, docs, tests, new tools. See **[CONTRIBUTING.md](CONTRIBUTING.md)** for the contribution guide and **[DEVELOPMENT.md](DEVELOPMENT.md)** for setup and workflow.
|
|
1638
1138
|
|
|
1639
|
-
|
|
1640
|
-
- Questions? Open a [Discussion](https://github.com/williamzujkowski/live-coding-music-mcp/discussions)
|
|
1641
|
-
- Found something confusing? Tell us!
|
|
1642
|
-
- Have a use case we haven't considered? Share it!
|
|
1139
|
+
For non-trivial work, open a GitHub issue first ([issue policy in CLAUDE.md](CLAUDE.md#github-issues-workflow)). For typos and small fixes, a PR directly is fine.
|
|
1643
1140
|
|
|
1644
|
-
|
|
1141
|
+
[GitHub Discussions](https://github.com/williamzujkowski/live-coding-music-mcp/discussions) are open for use-case questions and design conversations.
|
|
1645
1142
|
|
|
1646
|
-
##
|
|
1143
|
+
## License
|
|
1647
1144
|
|
|
1648
1145
|
**AGPL-3.0-or-later** — see [LICENSE](LICENSE) for the full text.
|
|
1649
1146
|
|
|
1650
1147
|
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).
|
|
1651
1148
|
|
|
1652
|
-
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.
|
|
1149
|
+
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 (current: v4.0.0).
|
|
1653
1150
|
|
|
1654
|
-
##
|
|
1151
|
+
## Acknowledgments
|
|
1655
1152
|
|
|
1656
|
-
- [Strudel.cc](https://strudel.cc) -
|
|
1657
|
-
- [TidalCycles](https://tidalcycles.org)
|
|
1658
|
-
- [Anthropic](https://anthropic.com)
|
|
1659
|
-
- [Playwright](https://playwright.dev)
|
|
1153
|
+
- [Strudel.cc](https://strudel.cc) — pattern-based live coding environment (this project is a fan adapter, not affiliated)
|
|
1154
|
+
- [TidalCycles](https://tidalcycles.org) — original pattern language Strudel descends from
|
|
1155
|
+
- [Anthropic](https://anthropic.com) — Claude and the MCP protocol
|
|
1156
|
+
- [Playwright](https://playwright.dev) — browser automation
|
|
1660
1157
|
|
|
1661
1158
|
---
|
|
1662
1159
|
|