Strudel Live Coding logo

Strudel Live Coding

Community
williamzujkowski

A Model Context Protocol (MCP) server that gives Claude direct control over Strudel.cc for AI-assisted music generation and live coding.

Publisherwilliamzujkowski
Repositorystrudel-mcp-server
LanguageTypeScript
Forks
24
Stars
200
Available tools
0
Transport typestdio
Categories
LicenseAGPL-3.0
Links
  • Connect tools to AI workflows

    Strudel Live Coding exposes MCP capabilities that can be used by compatible AI clients and agents.

  • 0 available tools

    Browse the callable actions below, including names and descriptions when provided by the server.

  • Ready-to-copy setup

    Use the installation snippets to configure this server in your preferred MCP client.

  • Open source signals

    200 stars and 24 forks from the linked repository.

live-coding-music-mcp

🎡 MCP server for AI-assisted live-coding music via strudel.cc

Unofficial fan project. Not affiliated with, or endorsed by, the Strudel project. This adapter exists to make live-coding music accessible to beginners who want to try pattern-based music without learning the whole ecosystem first.

Status: Beta | 86% statement coverage | Published to npm | Actively developed

CI npm version Nerq Trust Tools License

A Model Context Protocol (MCP) server that drives Strudel.cc from Claude for AI-assisted live-coding music, pattern generation, and algorithmic composition.

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.

What "Beta" means here:

  • Tool schemas are stable within minor versions; breaking changes require a major bump
  • Multi-session is supported as of v3.0.0 (#108) β€” named sessions get isolated browser, history, and audio-capture state
  • Upstream @strudel/* dependencies pinned to known-good versions; Dependabot bumps gated on CI
  • Expect hands-on iteration for non-standard patterns β€” report rough edges, they get fixed

Table of Contents

Features

🎹 Music control

  • 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).
  • 4 MCP resources for catalog browsing without burning tool calls: strudel://examples, strudel://patterns, strudel://styles, strudel://docs/tools.
  • Real browser automation of Strudel.cc through Playwright.
  • 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.
  • Audio analysis via Web Audio API (FFT spectrum, tempo detection, key detection, rhythm complexity).
  • 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.
  • Music theory helpers: 15+ scales, 8+ chord progression styles, euclidean and polyrhythm generation.
  • Pattern persistence: JSON-backed save/load with tags + the in-memory edit history (undo/redo/restore/compare).
  • Result envelope on every tools/call: clients branch on { ok, errorCategory, isRetryable } instead of parsing free-text.

πŸ”§ Testing & CI status

  • 1771 passing tests across unit, integration, and example-validation suites.
  • 86.76% statement coverage / 77.32% branch coverage.
  • Lint blocking in CI: 0 errors, ~163 warnings (mostly any in test mocks).
  • OIDC trusted publishing to npm with SLSA build provenance attestation on every release.

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 to help improve it.

🎼 Example patterns

18 example patterns ship in patterns/examples/, grouped by genre:

  • Techno: hard-techno, minimal-techno
  • House: deep-house, tech-house
  • Drum & Bass: liquid-dnb, neurofunk
  • Ambient: dark-ambient, drone
  • Trap: modern-trap, cloud-trap
  • Jungle: classic-jungle, ragga-jungle
  • Jazz: bebop, modal-jazz
  • Longform (multi-minute pieces): dark-ambient-journey, driving-techno, liquid-dnb-roller, nu-jazz-session

Each example is a JSON file with pattern code, BPM, key, and a description. See patterns/examples/README.md for details. Agents can also list these via the strudel://examples MCP resource without making any tool calls.

Migrating from @williamzujkowski/strudel-mcp-server

This project was renamed from @williamzujkowski/strudel-mcp-server to @williamzujkowski/live-coding-music-mcp to make the unofficial fan-project status unambiguous (see #97). The old package is deprecated on npm.

If you were using the old package:

bash
# Remove old
npm uninstall -g @williamzujkowski/strudel-mcp-server

# Install new
npm install -g @williamzujkowski/live-coding-music-mcp

Update your MCP client config. The bin name changed from strudel-mcp to live-coding-music-mcp:

jsonc
// BEFORE
{
  "mcpServers": {
    "strudel": { "command": "strudel-mcp" }
  }
}

// AFTER
{
  "mcpServers": {
    "live-coding-music": { "command": "live-coding-music-mcp" }
  }
}

The MCP server's internal identity string also changed from strudel-mcp-enhanced to live-coding-music-mcp. If you have a client that keys on that string (logs, allowlists, permission policies), update it accordingly.

All tool names and schemas are unchanged.

Installation

Prerequisites

RequirementVersionNotes
Node.js22.x+LTS required
npm10+Comes with Node.js
ChromiumLatestAuto-installed by Playwright
Audio outputAnyRequired for playback (speakers/headphones)

Optional: Docker for containerized deployment.

From npm

bash
npm install -g @williamzujkowski/live-coding-music-mcp

# Install browser (required once)
npx playwright install chromium

From Source

bash
# Clone repository
git clone https://github.com/williamzujkowski/live-coding-music-mcp.git
cd live-coding-music-mcp

# Install dependencies
npm install

# Install Chromium for browser automation
npx playwright install chromium

# Build the project
npm run build

Quick Reference

Common commands for immediate use:

ActionTool call
Initialize browserinit
Create a techno beat in one shotcompose({ style: "techno" })
Play patternplayback({ action: "play" })
Stop playbackplayback({ action: "stop" })
Get current patternget_pattern
Analyze audio (all features)analyze({ include: ["all"] })
Detect tempo onlyanalyze({ include: ["tempo"] })
Save patternpattern_store({ action: "save", name: "my-pattern" })
Undo last edithistory({ action: "undo" })
Edit current patternedit_pattern({ mode: "write", pattern: "..." })
Create an isolated sessionsession({ action: "create", session_id: "live-1" })

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).

One-shot workflow:

compose with style: "dnb", key: "Am", bpm: 174, auto_play: true

Quick Start

1. Add to Claude

bash
# If installed globally
claude mcp add strudel live-coding-music-mcp

# If built from source
claude mcp add strudel node /path/to/live-coding-music-mcp/dist/index.js

2. Start Using

bash
claude chat

Then ask Claude:

  • "Initialize Strudel and create a techno beat"
  • "Generate a jazz chord progression in F major"
  • "Create a drum & bass pattern at 174 BPM"

Available Tools

84 tools across 15 categories:

ToolDescription
initInitialize Strudel in browser
ToolDescription
get_patternGet current pattern code
write[DEPRECATED β€” use edit_pattern({ mode: "write" }) instead] Write pattern to editor with optional auto-play and validation
append[DEPRECATED β€” use edit_pattern({ mode: "append" }) instead] Append code to current pattern
insert[DEPRECATED β€” use edit_pattern({ mode: "insert" }) instead] Insert code at specific line
replace[DEPRECATED β€” use edit_pattern({ mode: "replace" }) instead] Replace pattern section
ToolDescription
status[DEPRECATED β€” use diagnostics({ level: "status" }) instead] Get current browser and playback status (quick state check)
clear[DEPRECATED β€” use edit_pattern({ mode: "clear" }) instead] Clear the editor
play[DEPRECATED β€” use playback({ action: "play" }) instead] Start playing pattern
pause[DEPRECATED β€” use playback({ action: "pause" }) instead] Pause playback
stop[DEPRECATED β€” use playback({ action: "stop" }) instead] Stop playback
set_tempoSet BPM
ToolDescription
save[DEPRECATED β€” use pattern_store({ action: "save" }) instead] Save pattern with metadata
load[DEPRECATED β€” use pattern_store({ action: "load" }) instead] Load saved pattern
list[DEPRECATED β€” use pattern_store({ action: "list" }) instead] List saved patterns
ToolDescription
undo[DEPRECATED β€” use history({ action: "undo" }) instead] Undo last action
redo[DEPRECATED β€” use history({ action: "redo" }) instead] Redo action
list_history[DEPRECATED β€” use history({ action: "list" }) instead] List recent pattern history with timestamps and previews
restore_history[DEPRECATED β€” use history({ action: "restore" }) instead] Restore a previous pattern from history by ID
ToolDescription
composeGenerate, write, and play a complete pattern in one step. Auto-initializes default browser if needed.
generate_pattern[DEPRECATED β€” use compose instead, which auto-inits and returns richer metadata] Generate complete pattern from style with optional auto-play.
generate_drums[DEPRECATED β€” use generate_part({ role: "drums" }) instead] Generate drum pattern
generate_bassline[DEPRECATED β€” use generate_part({ role: "bass" }) instead] Generate bassline
generate_melody[DEPRECATED β€” use generate_part({ role: "melody" }) instead] Generate melody from scale
generate_polyrhythm[DEPRECATED β€” use generate_rhythm({ type: "polyrhythm" }) instead] Generate polyrhythm
generate_fill[DEPRECATED β€” use generate_part({ role: "fill" }) instead] Generate drum fill
generate_variation[DEPRECATED β€” use transform({ op: "vary" }) instead] Create pattern variations (mis-named today; it transforms, not generates)
ToolDescription
generate_scale[DEPRECATED β€” use music_theory({ query: "scale" }) instead] Generate scale notes
generate_chord_progression[DEPRECATED β€” use music_theory({ query: "chord_progression" }) instead] Generate chord progression
generate_euclidean[DEPRECATED β€” use generate_rhythm({ type: "euclidean" }) instead] Generate Euclidean rhythm
apply_scale[DEPRECATED β€” use transform({ op: "scale" }) instead] Apply scale to notes
ToolDescription
transpose[DEPRECATED β€” use transform({ op: "transpose" }) instead] Transpose notes by semitones
reverse[DEPRECATED β€” use transform({ op: "reverse" }) instead] Reverse pattern
stretch[DEPRECATED β€” use transform({ op: "stretch" }) instead] Time stretch pattern
quantize[DEPRECATED β€” use transform({ op: "quantize" }) instead] Quantize to grid
humanize[DEPRECATED β€” use transform({ op: "humanize" }) instead] Add human timing variation
add_effect[DEPRECATED β€” use effect({ action: "add" }) instead] Add effect to pattern
remove_effect[DEPRECATED β€” use effect({ action: "remove" }) instead] Remove effect
add_swing[DEPRECATED β€” use transform({ op: "swing" }) instead] Add swing to pattern
set_energy[DEPRECATED β€” use shape({ dimension: "energy" }) instead] Adjust energy level 0-10. Auto-plays after applying.
ToolDescription
get_pattern_feedback[DEPRECATED β€” use ai_assist({ task: "feedback" }) instead] Get AI-powered creative feedback on the current pattern using Google Gemini.
jam_with[DEPRECATED β€” use ai_assist({ task: "jam" }) instead] AI generates a complementary layer to jam with your pattern.
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.
refine[DEPRECATED β€” use shape({ dimension: "refine" }) instead] Incrementally refine current pattern: faster/slower/louder/quieter/brighter/darker/"more reverb"/drier.
ToolDescription
analyzeAudio analysis on the currently-playing pattern.
analyze_spectrum[DEPRECATED β€” use analyze({ include: ["spectrum"] }) instead] FFT spectrum analysis
analyze_rhythm[DEPRECATED β€” use analyze({ include: ["rhythm"] }) instead] Rhythm analysis
detect_tempo[DEPRECATED β€” use analyze({ include: ["tempo"] }) instead] BPM detection
detect_key[DEPRECATED β€” use analyze({ include: ["key"] }) instead] Key detection
validate_pattern_runtimeValidate pattern with runtime error checking (monitors Strudel console for errors)
compare_patterns[DEPRECATED β€” use history({ action: "compare" }) instead] Compare two patterns from history showing differences
ToolDescription
create_session[DEPRECATED β€” use session({ action: "create" }) instead] Create a new isolated Strudel browser session.
destroy_session[DEPRECATED β€” use session({ action: "destroy" }) instead] Close and destroy a Strudel session.
list_sessions[DEPRECATED β€” use session({ action: "list" }) instead] List all active Strudel sessions.
switch_session[DEPRECATED β€” use session({ action: "switch" }) instead] Change the default session.
ToolDescription
export_midiExport current pattern to MIDI file. Parses note(), n(), and chord() functions.
screenshot[DEPRECATED β€” use browser_window({ action: "screenshot" }) instead] Take a screenshot of the current Strudel editor state
ToolDescription
start_audio_capture[DEPRECATED β€” use audio_capture({ action: "start" }) instead] Start capturing audio. Audio must be playing.
stop_audio_capture[DEPRECATED β€” use audio_capture({ action: "stop" }) instead] Stop audio capture and return base64-encoded audio.
capture_audio_sample[DEPRECATED β€” use audio_capture({ action: "sample" }) instead] Capture a fixed-duration audio sample.
ToolDescription
show_browser[DEPRECATED β€” use browser_window({ action: "show" }) instead] Bring browser window to foreground
diagnosticsInspect server and browser state.
show_errors[DEPRECATED β€” use diagnostics({ level: "errors" }) instead] Display captured console errors and warnings from Strudel
performance_report[DEPRECATED β€” use diagnostics({ level: "perf" }) instead] Get performance metrics and bottlenecks
memory_usage[DEPRECATED β€” use diagnostics({ level: "memory" }) instead] Get current memory usage statistics
ToolDescription
ai_assistGemini-backed pattern assistance.
suggest_pattern_from_audio[DEPRECATED β€” use ai_assist({ task: "suggest" }) instead] Analyze playing audio and suggest a complementary Strudel pattern.
validate_pattern_localValidate pattern syntax against the in-process StrudelEngine (no browser required)
analyze_pattern_localStatic analysis (events/cycle, complexity, optional BPM) without browser playback
query_pattern_eventsEnumerate events the pattern would emit between two cycle indices (max 16 cycles)
transpile_patternTranspile pattern source via StrudelEngine; returns transpiled code or syntax error
audio_captureRecord audio output from the live Strudel session.
browser_windowInteract with the visible Strudel browser window.
edit_patternMutate the current session pattern.
generate_partGenerate a single instrumental layer and append it to the current session pattern.
music_theoryMusic-theory queries.
generate_rhythmGenerate a rhythmic pattern and append it to the current session.
historyNavigate or inspect the pattern edit history.
playbackControl transport on the current session.
sessionManage isolated Strudel browser sessions (multi-session, #108).
pattern_storePersist patterns to disk and read them back.
transformApply a single transform op to the current session pattern.
effectAdd or remove a Strudel effect on the current session pattern.
shapeShape the current pattern along one of three high-level dimensions.

Auto-generated from source. 84 tools registered.

Usage Examples

Basic Pattern Creation

Create a Simple Beat

You: Initialize Strudel and create a simple techno beat

Claude: [Initializes browser]
        [Generates and writes pattern]
        [Starts playback]

Pattern created:
setcpm(130)
stack(
  s("bd*4"),
  s("~ cp ~ cp"),
  s("hh*8").gain(0.4)
).gain(0.8)

Generate a Bassline

You: Add a techno bassline in C

Claude: [Generates bassline]
        [Appends to current pattern]

Added: note("c2 c2 c2 c2").s("sawtooth").cutoff(800)

Advanced Music Generation

Jazz Composition

You: Create a jazz progression in F major with a walking bass

Claude: Generated progression: "Gm7" "C7" "Fmaj7"

Pattern:
stack(
  note("Gm7" "C7" "Fmaj7").struct("1 ~ ~ ~").s("piano"),
  note("g2 c2 f2").s("sine").gain(0.7)
)

Drum & Bass Track

You: Generate a complete drum & bass track at 174 BPM

Claude: [Creates multi-layer pattern with drums, bass, and pads]

// dnb pattern in C at 174 BPM
setcpm(174)
stack(
  // Drums
  s("bd ~ ~ [bd bd] ~ ~ bd ~, ~ ~ cp ~ ~ cp ~ ~").fast(2),

  // Bass
  note("c1 ~ ~ c2 ~ c1 ~ ~").s("square").cutoff(400),

  // Pads (atmospheric)
  note("c3 eb3 g3 bb3").s("sawtooth")
    .attack(2).release(4).room(0.8).gain(0.6)
)

Real-Time Manipulation

Live Audio Analysis

You: Analyze what's playing and show me the frequency breakdown

Claude: Audio Analysis Results:
{
  "connected": true,
  "features": {
    "average": 78.5,
    "peak": 180,
    "peakFrequency": 120,
    "bass": 145,
    "mid": 82,
    "treble": 45,
    "isPlaying": true,
    "brightness": "balanced"
  }
}

Strong bass presence detected - typical for techno/house patterns.

Pattern Variations

You: Create a glitchy variation of the current pattern

Claude: [Applies glitch transformation]

Added: .sometimes(x => x.chop(8).rev).rarely(x => x.speed(-1))

Multi-Track Composition

Layered Ambient Track

You: Create an ambient soundscape with multiple layers

Claude: [Generates complex multi-layer pattern]

setcpm(90)
stack(
  // Deep bass drone
  note("c1").s("sine").attack(4).release(8).gain(0.5),

  // Texture pad
  note("c3 eb3 g3").s("sawtooth")
    .attack(2).release(6).room(0.9).gain(0.4),

  // Sparse percussion
  s("bd ~ ~ ~, ~ ~ ~ hh:8").room(0.9).gain(0.3),

  // Melodic sparkles
  note("c5 g5 eb5 bb5").struct("~ 1 ~ 1 ~ ~ 1 ~")
    .s("triangle").delay(0.5).room(0.8).gain(0.3)
)

Session Management

Save and Load Patterns

You: Save this pattern as "techno-groove-1" with tags "techno" and "experimental"

Claude: Pattern saved as "techno-groove-1"

---

You: List all my techno patterns

Claude: Saved patterns with tag "techno":
β€’ techno-groove-1 [techno, experimental] - 2025-10-23T19:30:00.000Z
β€’ acid-bassline [techno, acid] - 2025-10-23T18:15:00.000Z

---

You: Load "acid-bassline"

Claude: Loaded pattern "acid-bassline"
[Pattern written to editor]

Music Theory Applications

Generate Euclidean Rhythms

You: Create a 5/8 euclidean rhythm with kick drum

Claude: Generated Euclidean rhythm (5/8)

Pattern: s("bd").struct("1 ~ 1 ~ 1 1 ~ 1")

Complex Polyrhythms

You: Generate a polyrhythm with kick (4/16), snare (7/16), and hi-hat (3/16)

Claude: Generated polyrhythm

stack(
  s("bd").euclid(4, 16),
  s("cp").euclid(7, 16),
  s("hh").euclid(3, 16)
)

Integration with LLM Agents

AI-Assisted Composition

You: Analyze the mood of my current pattern and suggest complementary elements

Claude: [Analyzes pattern structure and audio features]

Your pattern has:
- Energetic rhythm (130 BPM)
- Strong bass presence
- Minimal melodic content

Suggestions:
1. Add arpeggiated synth for movement
2. Include occasional breaks/fills
3. Layer atmospheric pad for depth

Would you like me to add any of these?

You: Add an arpeggiated synth in C minor

Claude: [Generates and adds]

note("c4 eb4 g4 bb4 c5").struct("1 1 1 1 1 1 1 1")
  .s("triangle").delay(0.25).room(0.3).gain(0.5)

Testing

All tools have been tested with real Strudel.cc interaction:

bash
# Run integration tests
npm run test:integration

# Run browser tests
node tests/strudel-integration.js

# Run npm test to see current pass/fail/skip counts

Configuration

config.json

json
{
  "headless": false,        // Set true for background operation
  "strudel_url": "https://strudel.cc/",
  "patterns_dir": "./patterns",
  "audio_analysis": {
    "fft_size": 2048,
    "smoothing": 0.8
  }
}

Architecture

System Overview

The Strudel MCP Server is built with a modular architecture that separates concerns and enables robust music generation:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Claude AI                              β”‚
β”‚                  (MCP Client)                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ MCP Protocol (stdio)
                        β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              StrudelMCPServer                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  Tool Request Handler                                  β”‚ β”‚
β”‚  β”‚  - Validates inputs                                    β”‚ β”‚
β”‚  β”‚  - Routes to appropriate service                       β”‚ β”‚
β”‚  β”‚  - Handles errors gracefully                           β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚            β”‚            β”‚           β”‚
   β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”  β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”  β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”  β”Œβ”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
   β”‚ Strudel β”‚  β”‚ Music  β”‚  β”‚Pattern β”‚  β”‚ Pattern β”‚
   β”‚Controllerβ”‚  β”‚ Theory β”‚  β”‚Generatorβ”‚  β”‚  Store  β”‚
   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
   β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   Playwright Browser            β”‚
   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
   β”‚  β”‚   Strudel.cc Website     β”‚   β”‚
   β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
   β”‚  β”‚  β”‚  CodeMirror Editor β”‚  β”‚   β”‚
   β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚
   β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
   β”‚  β”‚  β”‚  Audio Context     β”‚  β”‚   β”‚
   β”‚  β”‚  β”‚  + Web Audio API   β”‚  β”‚   β”‚
   β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚
   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚ Audio Analyzer β”‚
          β”‚  - FFT Analysisβ”‚
          β”‚  - Frequency   β”‚
          β”‚  - Spectral    β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Components

1. StrudelMCPServer (src/server/server.ts, ~510 lines)

Thin MCP dispatcher that:

  • Aggregates 84 tool definitions from the per-domain modules in src/server/tools/ (84 = 26 consolidated tools + 58 deprecated aliases; -58 once #178 lands)
  • Routes tools/call requests to the right module's execute()
  • Wraps every response in the discriminated result envelope ({ ok, errorCategory, isRetryable, ... })
  • Tracks initialization, per-session history bundles, per-session audio capture services
  • Advertises and serves MCP resources (strudel://examples, etc.)
  • Lazy-initializes the default browser controller on first browser-touching call

Key Features:

typescript
- Pattern caching before browser init
- Undo/redo stack management
- Session history tracking
- Generated pattern storage
- Safe fallback mechanisms

2. StrudelController (src/StrudelController.ts)

Browser automation layer using Playwright:

  • Browser Management: Chromium instance lifecycle
  • Editor Control: CodeMirror manipulation via DOM
  • Playback Control: Keyboard shortcuts for play/stop
  • Performance Optimizations:
    • Editor content caching (100ms TTL)
    • Direct CodeMirror API access
    • Resource blocking (images, fonts)
    • Fast DOM content loading
typescript
// Example: Optimized pattern writing
async writePattern(pattern: string) {
  await this.page.evaluate((newPattern) => {
    const editor = document.querySelector('.cm-content');
    const view = editor.__view;
    view.dispatch({
      changes: { from: 0, to: view.state.doc.length, insert: newPattern }
    });
  }, pattern);
}

3. AudioAnalyzer (src/AudioAnalyzer.ts)

Real-time audio analysis via Web Audio API injection:

  • FFT Analysis: 1024-point FFT for spectral data
  • Frequency Bands: Bass, low-mid, mid, high-mid, treble
  • Analysis Caching: 50ms TTL for performance
  • Features Extracted:
    • Average amplitude
    • Peak frequency
    • Spectral centroid
    • Playing state detection
    • Frequency distribution
typescript
Features provided:
- average: Overall amplitude (0-255)
- peak: Maximum amplitude
- peakFrequency: Dominant frequency in Hz
- bass/mid/treble: Band-specific amplitudes
- brightness: Timbral classification
- isPlaying: Boolean playback state

4. MusicTheory (src/services/MusicTheory.ts)

Music theory engine providing:

  • 15+ Scales: Major, minor, modes, pentatonic, blues, whole-tone
  • Chord Progressions: Pop, jazz, blues, rock, folk, EDM
  • Euclidean Rhythms: Mathematical rhythm generation
  • Arpeggio Generation: Multiple patterns (up, down, random)
  • Note Transposition: Semitone-based pitch shifting

Supported scales:

typescript
major, minor, dorian, phrygian, lydian, mixolydian,
aeolian, locrian, pentatonic, blues, chromatic,
wholetone, harmonic_minor, melodic_minor

5. PatternGenerator (src/services/PatternGenerator.ts)

AI-powered pattern creation:

  • Genre Templates: Techno, house, DnB, trap, ambient, jazz, intelligent_dnb, trip_hop, boom_bap
  • Drum Patterns: 4 complexity levels per genre
  • Basslines: 8 different styles
  • Melody Generation: Scale-based with musical intervals
  • Variations: Subtle, moderate, extreme, glitch, evolving
  • Fills: 1-4 bar drum fills

Example generation:

typescript
generateCompletePattern('techno', 'C', 130)
β†’ Multi-layer pattern with drums, bass, chords, melody

6. PatternStore (src/PatternStore.ts)

Persistent pattern storage:

  • JSON-based: Simple file storage
  • Metadata: Name, tags, timestamp, audio features
  • Tag Filtering: Organize by genre, mood, project
  • Sorted Retrieval: Most recent first

Directory Structure

live-coding-music-mcp/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ server/
β”‚   β”‚   β”œβ”€β”€ server.ts                    # MCP dispatcher (~510 lines)
β”‚   β”‚   β”œβ”€β”€ resources.ts                 # MCP resources (#131)
β”‚   β”‚   └── tools/
β”‚   β”‚       β”œβ”€β”€ ai.ts, analysis.ts, capture.ts, compose.ts,
β”‚   β”‚       β”œβ”€β”€ diagnostics.ts, editor.ts, generate.ts, history.ts,
β”‚   β”‚       β”œβ”€β”€ playback.ts, session.ts, storage.ts, transform.ts,
β”‚   β”‚       └── types.ts                 # ToolContext, Envelope, helpers
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ MusicTheory.ts                # Scale/chord/euclidean helpers
β”‚   β”‚   β”œβ”€β”€ PatternGenerator.ts           # Template-based generation
β”‚   β”‚   β”œβ”€β”€ SessionManager.ts             # Multi-session lifecycle (#108)
β”‚   β”‚   β”œβ”€β”€ AudioCaptureService.ts        # Audio recording
β”‚   β”‚   β”œβ”€β”€ MIDIExportService.ts          # MIDI export
β”‚   β”‚   β”œβ”€β”€ GeminiService.ts              # Gemini API client (ai_assist)
β”‚   β”‚   β”œβ”€β”€ StrudelEngine.ts              # @strudel/* wrapper
β”‚   β”‚   └── StrudelEngineHelpers.ts       # Pure helpers (#107)
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ Logger.ts
β”‚   β”‚   β”œβ”€β”€ PatternValidator.ts           # Syntax + safety checks
β”‚   β”‚   β”œβ”€β”€ ErrorRecovery.ts              # Retry / backoff
β”‚   β”‚   β”œβ”€β”€ PerformanceMonitor.ts
β”‚   β”‚   └── InputValidator.ts             # Input bound checks
β”‚   β”œβ”€β”€ StrudelController.ts              # Browser automation (~800 lines)
β”‚   β”œβ”€β”€ AudioAnalyzer.ts                  # Audio analysis (~800 lines)
β”‚   β”œβ”€β”€ PatternStore.ts                   # On-disk pattern persistence
β”‚   └── index.ts                          # Entry point
β”œβ”€β”€ src/__tests__/                        # Jest suites (unit + integration + browser)
β”œβ”€β”€ patterns/
β”‚   β”œβ”€β”€ examples/                         # 18 bundled example patterns
β”‚   └── *.json                            # Saved patterns at runtime
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ generate-tool-docs.ts             # README tool-table generator
β”‚   └── generate-changelog.ts
β”œβ”€β”€ config.json                           # Local config (gitignored)
β”œβ”€β”€ package.json
└── tsconfig.json

Data Flow

  1. Tool Invocation

    Claude β†’ MCP Protocol β†’ StrudelMCPServer
  2. Pattern Generation (without browser)

    Server β†’ PatternGenerator β†’ MusicTheory β†’ Pattern String
  3. Pattern Execution (with browser)

    Server β†’ StrudelController β†’ Playwright β†’ Strudel.cc
  4. Audio Analysis

    Strudel.cc β†’ Web Audio API β†’ AudioAnalyzer β†’ Feature Data

Performance Characteristics

OperationLatencyNotes
Pattern Generation<100msPure computation
Browser Init~3sOne-time cost
Pattern Write~50msWith caching
Play/Stop~100msKeyboard shortcuts
Audio Analysis~20msWith 50ms cache
Pattern Save~10msFile I/O

Optimization Strategies

  1. Caching

    • Editor content: 100ms TTL
    • Audio analysis: 50ms TTL
    • Generated patterns: Until browser init
  2. Resource Blocking

    • Images, fonts, media blocked
    • Only load essential JavaScript/CSS
  3. Direct API Access

    • CodeMirror view manipulation
    • Keyboard shortcuts over button clicks
  4. Lazy Loading

    • Browser starts only when needed
    • Services initialized on-demand

Pattern Examples

Minimal Techno (Verified Working)

javascript
setcpm(130)
stack(
  s("bd*4").gain(0.9),
  s("~ cp ~ cp").room(0.2),
  s("hh*16").gain(0.4).pan(sine.range(-0.5, 0.5)),
  note("c2 c2 eb2 c2").s("sawtooth").cutoff(800)
).swing(0.05)

Drum & Bass (Verified Working)

javascript
setcpm(174)
stack(
  s("bd ~ ~ [bd bd] ~ ~ bd ~, ~ ~ sn:3 ~ ~ sn:3 ~ ~").fast(2),
  s("hh*16").gain(0.5),
  note("e1 ~ ~ e2 ~ e1 ~ ~").s("sine:2").lpf(200)
)

Generated Jazz Progression

javascript
// Jazz ii-V-I in F
stack(
  note("Gm7" "C7" "Fmaj7").struct("1 ~ ~ ~").s("piano"),
  note("g2 c2 f2").s("sine").gain(0.7)
)

Docker Support

bash
# Build image
docker build -t live-coding-music-mcp .

# Run container
docker run -it --rm live-coding-music-mcp

# Or use docker-compose
docker-compose up

Development

Setup Development Environment

bash
# Clone the repository
git clone https://github.com/williamzujkowski/live-coding-music-mcp.git
cd live-coding-music-mcp

# Install dependencies
npm install

# Install Playwright browsers
npx playwright install chromium

# Build the project
npm run build

Available Scripts

bash
# Development mode with hot reload
npm run dev

# Build TypeScript to dist/
npm run build

# Start production server
npm start

# Run all tests
npm test

# Run integration tests with real browser
npm run test:integration

# Run browser-specific tests
npm run test:browser

# Validate MCP protocol compliance
npm run validate

# Lint code
npm run lint

# Format code
npm run format

# Clean build artifacts
npm clean

Publishing to npm

See NPM_PUBLISHING.md for complete publishing instructions.

Quick publish via GitHub Release:

bash
npm version patch  # or minor, major
git push && git push --tags
gh release create v$(node -p "require('./package.json').version") --generate-notes

The package uses OIDC trusted publishing with provenance attestation for supply chain security.

Adding new tools

Tools live in per-domain modules under src/server/tools/<domain>.ts. server.ts just dispatches. To add a tool:

  1. Pick the right domain module (or add a new one). Add the tool definition to that module's tools array:

    typescript
    export const tools: Tool[] = [
      // ...
      {
        name: 'my_new_tool',
        description: 'One-line description; agents read this to pick between adjacent tools',
        inputSchema: {
          type: 'object',
          properties: {
            param1: { type: 'string', description: 'What it is' },
            session_id: { type: 'string', description: 'Optional session ID (#108)' },
          },
          required: ['param1'],
        },
      },
    ];
  2. Add the case to the module's execute() switch:

    typescript
    case 'my_new_tool':
      return await ctx.getController(args.session_id).doSomething(args.param1);
  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.

  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.

  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.

  6. Build and test:

    bash
    npm run build
    echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"my_new_tool","arguments":{"param1":"test"}},"id":2}' | node dist/index.js

Testing Strategy

1. Unit Tests

bash
# Run with Jest
npm test

# Watch mode
npm run test:watch

2. Integration Tests

bash
# Full integration with real browser
npm run test:integration

# This tests:
# - Browser initialization
# - Pattern generation
# - Audio analysis
# - Pattern storage
# - All 84 registered tools

3. Manual Testing

bash
# Development mode
npm run dev

# In another terminal
claude mcp add strudel-dev node $(pwd)/dist/index.js
claude chat

# Then interact with Claude

Code Quality

TypeScript Configuration

json
// tsconfig.json
{
  "compilerOptions": {
    "strict": true,           // Strict type checking
    "esModuleInterop": true,  // Better module compatibility
    "target": "ES2020",       // Modern JavaScript
    "module": "ES2020",       // ES modules
    "moduleResolution": "node"
  }
}

Linting & Formatting

bash
# ESLint
npm run lint

# Prettier
npm run format

# Pre-commit hooks recommended

Debugging

Enable Debug Logging

bash
# Set DEBUG environment variable
DEBUG=strudel:* npm start

# Or specific modules
DEBUG=strudel:controller npm start
DEBUG=strudel:audio npm start

VS Code Launch Configuration

json
{
  "type": "node",
  "request": "launch",
  "name": "Debug MCP Server",
  "program": "${workspaceFolder}/dist/index.js",
  "preLaunchTask": "npm: build",
  "console": "integratedTerminal",
  "env": {
    "DEBUG": "strudel:*"
  }
}

Playwright Debugging

typescript
// In StrudelController.ts
this.browser = await chromium.launch({
  headless: false,  // See the browser
  devtools: true,   // Open DevTools
  slowMo: 100       // Slow down actions
});

Performance Monitoring

The server includes built-in performance monitoring:

typescript
// Access performance metrics
You: Show me performance metrics

Claude: Performance Report:
{
  "averageLatency": {
    "init": "3.2s",
    "write": "52ms",
    "play": "105ms",
    "analyze": "18ms"
  },
  "cacheHitRate": "85%",
  "totalOperations": 1247,
  "bottlenecks": [
    {"tool": "init", "avgTime": 3200, "calls": 1},
    {"tool": "write", "avgTime": 52, "calls": 156}
  ]
}

Contributing Guidelines

  1. Fork the repository

    bash
    git clone https://github.com/YOUR_USERNAME/live-coding-music-mcp.git
  2. Create a feature branch

    bash
    git checkout -b feature/my-new-feature
  3. Make your changes

    • Follow existing code style
    • Add tests for new features
    • Update documentation
    • Ensure all tests pass
  4. Commit with meaningful messages

    bash
    git commit -m "feat: Add support for custom scale generation"

    Follow Conventional Commits:

    • feat: New feature
    • fix: Bug fix
    • docs: Documentation changes
    • refactor: Code refactoring
    • test: Adding tests
    • chore: Maintenance tasks
  5. Push and create PR

    bash
    git push origin feature/my-new-feature

    Then create a Pull Request on GitHub with:

    • Clear description of changes
    • Link to related issues
    • Screenshots/examples if relevant

Release Process

bash
# 1. Update version in package.json
npm version patch  # or minor/major

# 2. Update CHANGELOG.md
# Add entry for new version

# 3. Build and test
npm run build
npm test
npm run test:integration

# 4. Commit version bump
git add .
git commit -m "chore: Bump version to X.Y.Z"

# 5. Create git tag
git tag vX.Y.Z

# 6. Push to GitHub
git push origin main --tags

# 7. Publish to npm (if you have access)
npm publish --access public

# 8. Create GitHub release
gh release create vX.Y.Z --generate-notes

Docker Development

bash
# Build development image
docker build -t live-coding-music-mcp:dev .

# Run with volume mount for hot reload
docker run -it --rm \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/patterns:/app/patterns \
  live-coding-music-mcp:dev

# Run tests in container
docker run -it --rm live-coding-music-mcp:dev npm test

Environment Variables

bash
# Logging level
LOG_LEVEL=debug        # debug, info, warn, error

# Performance monitoring
ENABLE_PERF_MONITORING=true

# Pattern storage
PATTERNS_DIR=./patterns

# Browser configuration
HEADLESS=false
BROWSER_TIMEOUT=15000

# Audio analysis
FFT_SIZE=1024
SMOOTHING=0.8

Performance

Measured against the current StrudelController cache + Strudel.cc on a developer machine:

OperationLatency
Browser initialization1.5–2 s (with resource blocking)
Pattern write50–80 ms (cached CodeMirror editor access)
Pattern read (cached)10–15 ms
Play / pause / stop100–150 ms
Audio analysis (single FFT)10–15 ms
Tempo detection<100 ms (onset-based; degraded under headless audio)
Key detection<100 ms (Krumhansl-Schmuckler)
Pattern generation<100 ms (template-based)
Process resident memory~120–150 MB

Advanced Usage

Custom Music Theory

Create Custom Scales

typescript
// The MusicTheory service supports 15+ built-in scales
// You can request any combination:

You: Generate a lydian scale starting on D

Claude: D lydian scale: D, E, F#, G#, A, B, C#

Complex Chord Progressions

typescript
You: Create a jazz ii-V-I progression in Bb with extended voicings

Claude: Generated jazz progression in Bb: "Cm7" "F7" "Bbmaj7"

Pattern:
note("Cm7" "F7" "Bbmaj7")
  .struct("1 ~ ~ ~")
  .s("sawtooth")
  .add(note("7"))  // Add 7th extensions
  .room(0.4)

Advanced Rhythm Techniques

Euclidean Patterns

You: Create a complex polyrhythm using euclidean patterns:
     - Bass drum: 7 hits in 16 steps
     - Snare: 5 hits in 16 steps
     - Hi-hat: 11 hits in 16 steps

Claude: [Generates mathematically perfect polyrhythm]

stack(
  s("bd").euclid(7, 16),
  s("cp").euclid(5, 16),
  s("hh").euclid(11, 16)
)

Generative Variations

You: Create 3 variations of my current pattern: subtle, moderate, and glitchy

Claude: [Generates three variants]

Version 1 (subtle):
original.sometimes(x => x.fast(2))

Version 2 (moderate):
original.every(4, x => x.rev).sometimes(x => x.fast(2))

Version 3 (glitchy):
original.sometimes(x => x.chop(8).rev).rarely(x => x.speed(-1))

Performance Optimization Tips

Pattern Caching

// The server caches patterns intelligently:
// - Generated patterns stored before browser init
// - Editor content cached for 100ms
// - Audio analysis cached for 50ms

// For fastest performance:
1. Generate patterns before initializing browser
2. Initialize once and reuse the session
3. Batch multiple changes together

Headless Mode

json
// In config.json:
{
  "headless": true,  // Faster, no GUI
  "strudel_url": "https://strudel.cc/",
  "patterns_dir": "./patterns"
}

Integration Patterns

Workflow Automation

You: Create a complete track:
     1. Start with techno drums at 130 BPM
     2. Add acid bassline in E
     3. Layer ambient pads
     4. Save as "track-001" with tags "techno", "acid", "experimental"

Claude: [Executes full workflow]
        [Initializes browser]
        [Generates drum pattern]
        [Adds bassline]
        [Layers pads]
        [Saves with metadata]

Complete! Pattern saved as "track-001"

Audio-Reactive Composition

You: Monitor the audio and suggest adjustments based on frequency balance

Claude: [Analyzes current playback]

Analysis shows:
- Bass: 180 (strong)
- Mid: 45 (weak)
- Treble: 30 (weak)

Recommendations:
1. Reduce bass gain by 20%
2. Add mid-range melodic content
3. Include hi-hat pattern for treble

Apply changes? [Yes/No]

Advanced Pattern Manipulation

Dynamic Transformations

You: Apply these transformations in sequence:
     1. Transpose up 3 semitones
     2. Add 10% humanization
     3. Apply reverb with 0.6 room size
     4. Every 4th cycle, reverse the pattern

Claude: [Applies transformations]

Final pattern:
[original]
  .transpose(3)
  .nudge(rand.range(-0.1, 0.1))
  .room(0.6)
  .every(4, x => x.rev)

Conditional Logic

You: Create a pattern that evolves:
     - Bars 1-4: Simple kick pattern
     - Bars 5-8: Add snare
     - Bars 9-16: Add full drum kit
     - Then loop with variations

Claude: [Generates evolving pattern]

s("bd*4")
  .struct("1 ~ ~ ~")
  .mask("<1 1 1 1 0 0 0 0>/4")  // First 4 bars
  .stack(
    s("~ cp ~ cp")
      .mask("<0 0 0 0 1 1 1 1>/8")  // Bars 5-8
  )
  // Full complexity from bar 9
  .every(8, x => x.sometimes(y => y.fast(2)))

πŸ”’ Security

Pattern Validation

All patterns are validated before execution:

  • Dangerous gain levels (>2.0) are flagged
  • Eval blocks are rejected
  • Path traversal attacks are blocked in PatternStore

Browser Sandboxing

  • Playwright runs Chromium in sandbox mode
  • No access to local filesystem from browser context
  • Resource blocking prevents loading external content

Known Limitations

  • No authentication: The MCP server trusts all incoming requests
  • Local only: Designed for local development, not network deployment
  • Pattern execution: Patterns execute in browser context with audio access

Reporting Security Issues

Found a vulnerability? Please open a security issue or email the maintainer directly. Do not disclose publicly until patched.

πŸ› Troubleshooting

Common Issues

Browser doesn't open

Symptom: Error: Browser not initialized or Chromium launch fails

Solutions:

bash
# Install Chromium for Playwright
npx playwright install chromium

# If that fails, try installing all browsers
npx playwright install

# Check Playwright installation
npx playwright --version

# For Linux, install dependencies
sudo npx playwright install-deps chromium

Audio analysis returns "not connected"

Symptom: Audio analysis shows connected: false

Solutions:

  1. Ensure pattern is playing first:

    You: Play the pattern, wait 2 seconds, then analyze
  2. Reinitialize the browser:

    You: Stop, close the browser, reinitialize, and try again
  3. Check audio context activation:

    • Audio contexts require user interaction on some systems
    • The browser window must be visible (not headless) for first run

Pattern syntax errors

Symptom: Pattern doesn't play or shows errors in console

Solutions:

Common issues:
1. Missing quotes: s(bd*4) β†’ s("bd*4")
2. Unmatched parentheses: stack(s("bd")) β†’ stack(s("bd")))
3. Invalid note names: note("h2") β†’ note("c2")

Test with minimal pattern first:
s("bd*4")

Then build complexity gradually.

MCP connection issues

Symptom: Claude can't find the server or tools

Solutions:

bash
# Verify server is built
npm run build

# Check if server responds
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js

# Should return JSON with 84 tools (post-v3.0; ~26 after #178 alias removal)

# Reinstall MCP server in Claude
claude mcp remove strudel
claude mcp add strudel node $(pwd)/dist/index.js

# Restart Claude
claude chat

Performance issues / Slow response

Symptom: Operations take longer than expected

Solutions:

  1. Enable caching (default, but verify):

    • Editor caching: 100ms TTL
    • Audio analysis: 50ms TTL
  2. Use headless mode for faster operation:

    json
    // config.json
    { "headless": true }
  3. Batch operations:

    Instead of:
    - Add drums
    - Add bass
    - Add melody
    
    Do:
    - Generate complete pattern with drums, bass, and melody
  4. Reduce browser overhead:

    • Close other browser instances
    • Disable browser DevTools
    • Use resource blocking (enabled by default)

Patterns not saving

Symptom: save command fails or patterns don't persist

Solutions:

bash
# Check patterns directory exists
ls -la ./patterns

# Create manually if needed
mkdir -p ./patterns

# Verify write permissions
touch ./patterns/test.json
rm ./patterns/test.json

# Check for invalid pattern names
# Valid: "techno-beat-1", "my_pattern", "track001"
# Invalid: "pattern/with/slashes", "name:with:colons"

Platform-Specific Issues

macOS

bash
# Keyboard shortcut uses Meta (Cmd) key
# Already handled by ControlOrMeta

# If Chromium crashes on M1/M2:
npx playwright install chromium --with-deps

Linux

bash
# Install system dependencies
sudo npx playwright install-deps chromium

# If running in Docker/headless environment:
# Ensure config.json has headless: true

Windows

bash
# Use PowerShell or Git Bash
# Paths should use forward slashes in config.json

# If Chromium doesn't launch:
npx playwright install chromium

Debugging Tips

Enable Verbose Logging

bash
# Set environment variable
DEBUG=* node dist/index.js

# Or in Claude:
You: Enable detailed logging for the next operation

Check Browser State

You: Show me the current browser initialization state
     and any cached patterns

Claude: Browser state:
- Initialized: true
- Cached patterns: 2
- Undo stack depth: 5
- Last operation: write_pattern (2.5s ago)

Validate Pattern Syntax

You: Before playing, validate this pattern syntax:
     s("bd*4, ~ cp ~ cp")

Claude: [Checks syntax]
Valid Strudel pattern.
Ready to play.

Getting Help

If you encounter issues not covered here:

  1. Check existing issues: GitHub Issues
  2. Run integration tests: npm run test:integration
  3. Enable debug mode: DEBUG=* npm start
  4. Consult Strudel docs: Strudel.cc documentation
  5. Create new issue: Include error messages, OS, Node version, and steps to reproduce

🀝 Contributing

We need your help! This project is actively developed and welcomes contributions of all kinds:

Ways to Contribute

  • Report Bugs: Found an issue? Open a bug report
  • Suggest Features: Have ideas? Create a feature request
  • Improve Docs: Fix typos, add examples, clarify confusing sections
  • Write Tests: Help us improve test coverage
  • Fix Issues: Check open issues for bugs to fix
  • Add Features: Implement new tools or improve existing ones

Quick Start for Contributors

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes and add tests
  4. Ensure tests pass (npm test)
  5. Commit with clear messages (git commit -m 'fix: resolve audio analysis bug')
  6. Push to your fork (git push origin feature/amazing-feature)
  7. Open a Pull Request

First time contributor? Look for issues labeled good-first-issue or help-wanted.

Feedback Welcome

  • Questions? Open a Discussion
  • Found something confusing? Tell us!
  • Have a use case we haven't considered? Share it!

We review PRs promptly and welcome contributors of all skill levels. See DEVELOPMENT.md for detailed setup instructions.

πŸ“„ License

AGPL-3.0-or-later β€” see LICENSE for the full text.

This project depends on @strudel/core, @strudel/mini, @strudel/tonal, and @strudel/transpiler, which are AGPL-3.0 licensed by the upstream Strudel project. 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).

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.

πŸ™ Acknowledgments


v3.0.0 β€” Open source, AGPL-3.0-or-later, experimental | Report issues | Contribute

This project is under active development. Core features work, but expect bugs and breaking changes. Not recommended for production use.

Installation

TypingMind
Prerequisites:

Node.js 18+

{
  "mcpServers": {
    "strudel-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@williamzujkowski/strudel-mcp-server"
      ]
    }
  }
}

Use Strudel Live Coding MCP with multiple AI models

TypingMind connects MCP tools at the workspace level, so once Strudel Live Coding is connected, you can use it with different AI models in TypingMind instead of setting it up separately for each model. This MCP runs locally through the TypingMind MCP connector on your device.

Setup guide to use the local connector

Use this when the MCP server needs access to local files, apps, or private resources on your computer.

1

Open the MCP settings

In TypingMind, go to Settings, Advanced Settings, then Model Context Protocol and choose Setup Connector.

  1. Open TypingMind in your browser.
  2. Click the Settings icon.
  3. Go to Advanced Settings.
  4. Open the Model Context Protocol section.
  5. Click Setup Connector and choose This Device.
TypingMind MCP connector setup screen with This Device selected
2

Run the connector command

Choose This Device, copy the command from TypingMind, and run it in Terminal. Keep the process running while you use MCP.

  1. Copy the setup command shown by TypingMind.
  2. Open Terminal on macOS or Windows Terminal on Windows.
  3. Paste and run the command.
  4. Approve the package install if Terminal asks you to proceed.
  5. Keep the Terminal window running while using MCP tools.
3

Add Strudel Live Coding as a server

When the connector status is Ready, click Edit Servers and paste the MCP server configuration.

  1. Wait until the connector status shows Ready.
  2. Click Edit Servers.
  3. Paste the Strudel Live Coding MCP server configuration.
  4. Save the server list.
  5. Refresh if you want to confirm the connector is still ready.
TypingMind MCP settings showing active server and Edit Servers button
{
  "mcpServers": {
    "strudel-live-coding": {
      "command": "npx",
      "args": [
        "-y",
        "@williamzujkowski/strudel-mcp-server"
      ]
    }
  }
}
4

Use it across models

Save the server list, open Plugins, enable the Strudel Live Coding MCP tools, then select any supported AI model in TypingMind and use the tools in chat or assign them to an AI agent.

  1. Open the Plugins page in TypingMind.
  2. Enable the Strudel Live Coding MCP tools.
  3. Start a chat and choose the AI model you want to use.
  4. Use the MCP tools in chat or assign them to an AI agent.
  5. Switch to another AI model whenever needed without reconnecting MCP.
TypingMind chat using enabled MCP tools with a selected AI model
Can you use Strudel Live Coding to help me with this task?
Strudel Live Coding
Sure. I read it.
Here is what I found using Strudel Live Coding.

Frequently asked questions

What is the Strudel Live Coding MCP server used for?

Strudel Live Coding is an MCP server that lets compatible AI clients connect to external tools and context. In TypingMind, you can add this MCP server once and make its tools available in your AI workspace.

Can I use Strudel Live Coding MCP with multiple AI models in TypingMind?

Yes. TypingMind connects MCP tools at the workspace level, so you can use Strudel Live Coding with different AI models such as Claude, ChatGPT, Gemini, or other models you have configured in TypingMind without setting up the MCP server separately for each model.

Why use Strudel Live Coding MCP with TypingMind?

TypingMind is one of the best frontends for LLM chat because it brings multiple AI models, prompts, plugins, AI agents, API keys, and MCP tools into one workspace. With Strudel Live Coding connected, you can use its MCP tools across your preferred models while keeping your chat workflow organized in TypingMind.

How do I connect Strudel Live Coding MCP to TypingMind?

Strudel Live Coding runs through the TypingMind local MCP connector. This is best when the MCP server needs access to local files, desktop apps, command-line tools, or private resources on your computer.

What tools does Strudel Live Coding MCP provide in TypingMind?

Strudel Live Coding exposes MCP capabilities that can be enabled from the TypingMind Plugins page and used in chat or assigned to AI agents.

Do I need to share my API keys with TypingMind to use Strudel Live Coding MCP?

No. TypingMind is local-first and lets you keep your model providers, API keys, prompts, and MCP configuration under your control. If Strudel Live Coding requires authentication, add the required headers, OAuth settings, or local configuration for that MCP server when you create the connection.

Related MCP Servers

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter πŸ‘‡