MCP Server / strudel
strudel
A Model Context Protocol (MCP) server that gives Claude direct control over Strudel.cc for AI-assisted music generation and live coding.
Installation
claude mcp add strudel -- npx -y @williamzujkowski/strudel-mcp-server
npx -y @williamzujkowski/strudel-mcp-server
npm: @williamzujkowski/strudel-mcp-server
Transport
Tools (20)
Experimental
Contributions welcome <a href="https://glama.ai/mcp/servers/@williamzujkowski/strudel-mcp-server"> <img width="380" height="200" src="https://glama.ai/mcp/servers/@williamzujkowski/strudel-mcp-serv
Version
Notes
npm
10+
Chromium
Latest
Any
Required for playback (speakers/headphones)
Action
Command
init
play
stop
get_pattern
analyze
undo
**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 strudel-mcp
Description
init
Initialize Strudel in browser
write
Write pattern to editor with optional auto-play and validation
append
Append code to current pattern
insert
Insert code at specific line
replace
Replace pattern section
get_pattern
Get current pattern code
play
Start playing pattern
Dokumentation
Strudel MCP Server
🎵 Open source MCP server for AI-powered music generation with Strudel.cc
Status: Actively developed | Experimental | Contributions welcome
An experimental Model Context Protocol (MCP) server that enables Claude to control Strudel.cc for AI-assisted music generation, live coding, and algorithmic composition.
Current State: Functional but under active development. Core features work reliably, but expect rough edges. See open issues for known limitations.
Table of Contents
- Features
- Installation
- Quick Reference
- Quick Start
- Available Tools
- Usage Examples
- Architecture
- Advanced Usage
- Configuration
- Security
- Troubleshooting
- Development
- Contributing
Features
🎹 Complete Music Control
- 65 MCP Tools: Comprehensive suite for music creation and manipulation
- Real Browser Automation: Direct control of Strudel.cc through Playwright
- Live Audio Analysis: Real-time frequency analysis via Web Audio API
- Pattern Generation: AI-powered creation across 8+ music genres
- Music Theory Engine: Scales, chords, progressions, euclidean rhythms
- Session Management: Save, load, undo/redo with pattern storage
🔧 Testing & Development Status
- ✅ Test Suite: Comprehensive test coverage across unit, integration, and validation tests
- ✅ Code Coverage: Actively tracked via CI
- ✅ Browser Integration: Works with live Strudel.cc website
- ✅ Audio Analysis: Real-time FFT analysis functional
- ✅ Pattern Generation: Core music generation features working
- ✅ OIDC Publishing: Secure npm publishing with provenance attestation
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
Explore 17 curated example patterns across 10 genres in patterns/examples/:
- Techno: Hard techno, minimal techno
- House: Deep house, tech house
- Drum & Bass: Liquid, neurofunk
- Ambient: Dark ambient, drone
- Trap: Modern trap, cloud trap
- Jungle: Classic jungle, ragga jungle
- Jazz: Bebop, modal jazz
- Intelligent DnB: Atmospheric, liquid, LTJ Bukem style
- Trip Hop: Portishead, Massive Attack, Flying Lotus style
- Boom Bap: DJ Premier, Alchemist, golden era hip hop
Each example includes pattern code, BPM, key, and description. See patterns/examples/README.md for details.
Installation
Prerequisites
| Requirement | Version | Notes | |-------------|---------|-------| | Node.js | 22.x+ | LTS required | | npm | 10+ | Comes with Node.js | | Chromium | Latest | Auto-installed by Playwright | | Audio output | Any | Required for playback (speakers/headphones) |
Optional: Docker for containerized deployment.
From npm
npm install -g @williamzujkowski/strudel-mcp-server
# Install browser (required once)
npx playwright install chromium
From Source
# Clone repository
git clone https://github.com/williamzujkowski/strudel-mcp-server.git
cd strudel-mcp-server
# 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:
| Action | Command |
|--------|---------|
| Initialize browser | init |
| Create techno beat | generate_pattern with style: "techno" |
| Play pattern | play |
| Stop playback | stop |
| Get current pattern | get_pattern |
| Analyze audio | analyze |
| Save pattern | save with name: "my-pattern" |
| Undo last change | undo |
One-shot workflow:
compose with style: "dnb", key: "Am", bpm: 174, auto_play: true
Quick Start
1. Add to Claude
# If installed globally
claude mcp add strudel strudel-mcp
# If built from source
claude mcp add strudel node /path/to/strudel-mcp-server/dist/index.js
2. Start Using
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
66 tools across 15 categories:
| Tool | Description |
|------|-------------|
| init | Initialize Strudel in browser |
| Tool | Description |
|------|-------------|
| write | Write pattern to editor with optional auto-play and validation |
| append | Append code to current pattern |
| insert | Insert code at specific line |
| replace | Replace pattern section |
| get_pattern | Get current pattern code |
| Tool | Description |
|------|-------------|
| play | Start playing pattern |
| pause | Pause playback |
| stop | Stop playback |
| clear | Clear the editor |
| set_tempo | Set BPM |
| status | Get current browser and playback status (quick state check) |
| Tool | Description |
|------|-------------|
| save | Save pattern with metadata |
| load | Load saved pattern |
| list | List saved patterns |
| Tool | Description |
|------|-------------|
| undo | Undo last action |
| redo | Redo action |
| list_history | List recent pattern history with timestamps and previews |
| restore_history | Restore a previous pattern from history by ID |
| Tool | Description |
|------|-------------|
| generate_variation | Create pattern variations |
| generate_pattern | Generate complete pattern from style with optional auto-play |
| generate_drums | Generate drum pattern |
| generate_bassline | Generate bassline |
| generate_melody | Generate melody from scale |
| generate_polyrhythm | Generate polyrhythm |
| generate_fill | Generate drum fill |
| compose | Generate, write, and play a complete pattern in one step. Auto-initializes browser if needed. |
| Tool | Description |
|------|-------------|
| apply_scale | Apply scale to notes |
| generate_scale | Generate scale notes |
| generate_chord_progression | Generate chord progression |
| generate_euclidean | Generate Euclidean rhythm |
| Tool | Description |
|------|-------------|
| transpose | Transpose notes by semitones |
| reverse | Reverse pattern |
| stretch | Time stretch pattern |
| quantize | Quantize to grid |
| humanize | Add human timing variation |
| add_effect | Add effect to pattern |
| remove_effect | Remove effect |
| add_swing | Add swing to pattern |
| set_energy | Adjust the overall energy level of the current pattern on a 0-10 scale. 0: minimal/ambient, 1-2: sparse, 3-4: light/relaxed, 5-6: normal/moderate, 7-8: driving/intense, 9-10: maximum. Auto-plays after applying energy level. |
| Tool | Description |
|------|-------------|
| shift_mood | Transform current pattern to match a different emotional mood by adjusting tempo, effects, and note choices. Moods: dark, euphoric, melancholic, aggressive, dreamy, peaceful, energetic. |
| get_pattern_feedback | Get AI-powered creative feedback on the current pattern using Google Gemini. Analyzes pattern structure and optionally audio. |
| refine | Incrementally refine the current pattern with simple directional commands. Supports: faster/slower (tempo), louder/quieter (gain), brighter/darker (filter cutoff), "more reverb"/drier (reverb). Auto-plays after applying refinement. |
| jam_with | AI generates a complementary layer to jam with your pattern. Analyzes current pattern to detect tempo, key, and existing layers, then generates a matching layer that fits musically. |
| Tool | Description |
|------|-------------|
| analyze | Complete audio analysis |
| analyze_spectrum | FFT spectrum analysis |
| analyze_rhythm | Rhythm analysis |
| detect_tempo | BPM detection |
| detect_key | Key detection |
| validate_pattern_runtime | Validate pattern with runtime error checking (monitors Strudel console for errors) |
| compare_patterns | Compare two patterns from history showing differences |
| Tool | Description |
|------|-------------|
| create_session | Create a new isolated Strudel browser session. Sessions share one browser but have isolated contexts. |
| destroy_session | Close and destroy a Strudel session, releasing its resources. |
| list_sessions | List all active Strudel sessions with their metadata. |
| switch_session | Change the default session used by other tools. |
| Tool | Description |
|------|-------------|
| screenshot | Take a screenshot of the current Strudel editor state |
| export_midi | Export current pattern to MIDI file. Parses note(), n(), and chord() functions. |
| Tool | Description |
|------|-------------|
| start_audio_capture | Start capturing audio from Strudel output. Audio must be playing for capture to work. |
| stop_audio_capture | Stop audio capture and return the recorded audio as base64-encoded data. |
| capture_audio_sample | Capture a fixed-duration audio sample from Strudel output. Audio must be playing. |
| Tool | Description |
|------|-------------|
| performance_report | Get performance metrics and bottlenecks |
| memory_usage | Get current memory usage statistics |
| show_browser | Bring browser window to foreground for visual feedback |
| diagnostics | Get detailed browser diagnostics including cache, errors, and performance |
| show_errors | Display captured console errors and warnings from Strudel |
| Tool | Description |
|------|-------------|
| suggest_pattern_from_audio | Analyze the currently playing audio and suggest a complementary Strudel pattern using Gemini AI. Extracts tempo, key, and spectral features locally, then uses AI to generate a matching pattern. Returns pattern text (not auto-executed). |
Auto-generated from source. 66 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:
# 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
{
"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)
Main MCP server implementation handling:
- 65 Tool Definitions: Complete API surface for music control
- Request Routing: Directs tool calls to appropriate handlers
- State Management: Tracks initialization, undo/redo stacks, pattern cache
- Error Handling: Graceful degradation and informative error messages
- Lazy Initialization: Browser starts only when needed
Key Features:
- 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
// 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
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:
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:
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
strudel-mcp-server/
├── src/
│ ├── server/
│ │ └── server.ts # MCP server
│ ├── services/
│ │ ├── MusicTheory.ts # Theory engine
│ │ └── PatternGenerator.ts # Pattern creation
│ ├── utils/
│ │ └── Logger.ts # Logging utility
│ ├── types/
│ │ └── index.ts # TypeScript types
│ ├── StrudelController.ts # Browser automation
│ ├── AudioAnalyzer.ts # Audio analysis
│ ├── PatternStore.ts # Pattern persistence
│ └── index.ts # Entry point
├── tests/
│ ├── browser-test.js # Browser integration
│ ├── integration.test.js # Integration tests
│ ├── manual-test.js # Manual testing
│ ├── mcp-tools.test.ts # MCP tool tests
│ └── strudel-integration.js # Full integration
├── patterns/ # Saved patterns
├── config.json # Server configuration
├── package.json # Dependencies
└── tsconfig.json # TypeScript config
Data Flow
-
Tool Invocation
Claude → MCP Protocol → StrudelMCPServer -
Pattern Generation (without browser)
Server → PatternGenerator → MusicTheory → Pattern String -
Pattern Execution (with browser)
Server → StrudelController → Playwright → Strudel.cc -
Audio Analysis
Strudel.cc → Web Audio API → AudioAnalyzer → Feature Data
Performance Characteristics
| Operation | Latency | Notes | |-----------|---------|-------| | Pattern Generation | <100ms | Pure computation | | Browser Init | ~3s | One-time cost | | Pattern Write | ~50ms | With caching | | Play/Stop | ~100ms | Keyboard shortcuts | | Audio Analysis | ~20ms | With 50ms cache | | Pattern Save | ~10ms | File I/O |
Optimization Strategies
-
Caching
- Editor content: 100ms TTL
- Audio analysis: 50ms TTL
- Generated patterns: Until browser init
-
Resource Blocking
- Images, fonts, media blocked
- Only load essential JavaScript/CSS
-
Direct API Access
- CodeMirror view manipulation
- Keyboard shortcuts over button clicks
-
Lazy Loading
- Browser starts only when needed
- Services initialized on-demand
Pattern Examples
Minimal Techno (Verified Working)
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)
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
// 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
# Build image
docker build -t strudel-mcp .
# Run container
docker run -it --rm strudel-mcp
# Or use docker-compose
docker-compose up
Development
Setup Development Environment
# Clone the repository
git clone https://github.com/williamzujkowski/strudel-mcp-server.git
cd strudel-mcp-server
# Install dependencies
npm install
# Install Playwright browsers
npx playwright install chromium
# Build the project
npm run build
Available Scripts
# 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:
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.
Project Structure
src/
├── server/
│ └── server.ts # MCP server
│
├── services/
│ ├── MusicTheory.ts # Music theory engine
│ │ - 15+ scales (major, minor, modes, etc.)
│ │ - Chord progressions (jazz, pop, blues, etc.)
│ │ - Euclidean rhythm generation
│ │ - Arpeggio generation
│ │
│ └── PatternGenerator.ts # Pattern creation service
│ - Genre-specific drum patterns
│ - Bassline generation
│ - Melody composition
│ - Pattern variations
│ - Complete track generation
│
├── utils/
│ ├── Logger.ts # Logging utility
│ ├── PerformanceMonitor.ts # Performance tracking
│ ├── PatternValidator.ts # Pattern syntax validation
│ └── ErrorRecovery.ts # Error handling & recovery
│
├── types/
│ └── index.ts # TypeScript type definitions
│
├── StrudelController.ts # Browser automation
│ - Chromium management via Playwright
│ - CodeMirror editor manipulation
│ - Playback control
│ - Pattern validation
│ - Error recovery
│
├── AudioAnalyzer.ts # Real-time audio analysis
│ - Web Audio API injection
│ - FFT spectral analysis
│ - Frequency band detection
│ - Playing state monitoring
│
├── PatternStore.ts # Pattern persistence
│ - JSON-based storage
│ - Tag-based organization
│ - Metadata tracking
│ - List caching
│
└── index.ts # Application entry point
Adding New Tools
To add a new MCP tool:
- Define the tool in
getTools()method:
{
name: 'my_new_tool',
description: 'Description of what it does',
inputSchema: {
type: 'object',
properties: {
param1: { type: 'string', description: 'Parameter description' },
param2: { type: 'number', description: 'Numeric parameter' }
},
required: ['param1']
}
}
- Implement the handler in
executeTool()switch statement:
case 'my_new_tool':
// Your implementation here
return await this.someService.doSomething(args.param1, args.param2);
- Add necessary service methods if needed:
// In appropriate service file
async doSomething(param1: string, param2?: number): Promise<string> {
// Implementation
return `Result: ${param1}`;
}
- Test the tool:
# Build
npm run build
# Test via MCP
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
# Run with Jest
npm test
# Watch mode
npm run test:watch
2. Integration Tests
# Full integration with real browser
npm run test:integration
# This tests:
# - Browser initialization
# - Pattern generation
# - Audio analysis
# - Pattern storage
# - All 65 tools
3. Manual Testing
# 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
// 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
# ESLint
npm run lint
# Prettier
npm run format
# Pre-commit hooks recommended
Debugging
Enable Debug Logging
# 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
{
"type": "node",
"request": "launch",
"name": "Debug MCP Server",
"program": "${workspaceFolder}/dist/index.js",
"preLaunchTask": "npm: build",
"console": "integratedTerminal",
"env": {
"DEBUG": "strudel:*"
}
}
Playwright Debugging
// 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:
// 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
-
Fork the repository
git clone https://github.com/YOUR_USERNAME/strudel-mcp-server.git -
Create a feature branch
git checkout -b feature/my-new-feature -
Make your changes
- Follow existing code style
- Add tests for new features
- Update documentation
- Ensure all tests pass
-
Commit with meaningful messages
git commit -m "feat: Add support for custom scale generation"Follow Conventional Commits:
feat:New featurefix:Bug fixdocs:Documentation changesrefactor:Code refactoringtest:Adding testschore:Maintenance tasks
-
Push and create PR
git push origin feature/my-new-featureThen create a Pull Request on GitHub with:
- Clear description of changes
- Link to related issues
- Screenshots/examples if relevant
Release Process
# 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
# Build development image
docker build -t strudel-mcp:dev .
# Run with volume mount for hot reload
docker run -it --rm \
-v $(pwd)/src:/app/src \
-v $(pwd)/patterns:/app/patterns \
strudel-mcp:dev
# Run tests in container
docker run -it --rm strudel-mcp:dev npm test
Environment Variables
# 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
- Pattern Generation: <100ms
- Browser Initialization: ~3 seconds
- Pattern Writing: Instant
- Playback Start: ~500ms
- Audio Analysis: Real-time
- Memory Usage: <150MB
Advanced Usage
Custom Music Theory
Create Custom Scales
// 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
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
// 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:
# 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:
-
Ensure pattern is playing first:
You: Play the pattern, wait 2 seconds, then analyze -
Reinitialize the browser:
You: Stop, close the browser, reinitialize, and try again -
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:
# 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 65 tools
# 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:
-
Enable caching (default, but verify):
- Editor caching: 100ms TTL
- Audio analysis: 50ms TTL
-
Use headless mode for faster operation:
// config.json { "headless": true } -
Batch operations:
Instead of: - Add drums - Add bass - Add melody Do: - Generate complete pattern with drums, bass, and melody -
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:
# 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
# Keyboard shortcut uses Meta (Cmd) key
# Already handled by ControlOrMeta
# If Chromium crashes on M1/M2:
npx playwright install chromium --with-deps
Linux
# Install system dependencies
sudo npx playwright install-deps chromium
# If running in Docker/headless environment:
# Ensure config.json has headless: true
Windows
# 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
# 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:
- Check existing issues: GitHub Issues
- Run integration tests:
npm run test:integration - Enable debug mode:
DEBUG=* npm start - Consult Strudel docs: Strudel.cc documentation
- 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
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes and add tests
- Ensure tests pass (
npm test) - Commit with clear messages (
git commit -m 'fix: resolve audio analysis bug') - Push to your fork (
git push origin feature/amazing-feature) - 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
MIT License - see LICENSE file
🙏 Acknowledgments
- Strudel.cc - Amazing live coding environment
- TidalCycles - Pattern language inspiration
- Anthropic - Claude AI and MCP protocol
- Playwright - Reliable browser automation
v2.4.0 - Open Source | Experimental | Report Issues | Contribute
This project is under active development. Core features work, but expect bugs and breaking changes. Not recommended for production use.