Atlas / MCP servers / williamzujkowski / Strudel

StrudelCAUTION

mcp/williamzujkowski/strudel

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

Verdict
CAUTION
Grade
B
Trust score
84 /100
Exposed tools
28 20r · 7w · 1d
Transport
stdio
License
AGPL-3.0
Stars
242
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

🎵 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 | 88% statement coverage | Published to npm | Actively developed

[](https://github.com/williamzujkowski/live-coding-music-mcp/actions) [](https://www.npmjs.com/package/@williamzujkowski/live-coding-music-mcp) [](https://nerq.ai/kya/live-coding-music-mcp) []() [](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 → compose → playback → analyze) works reliably with real audio output. npm test reports ~3060 passing tests, 88.99% statement coverage / 79.99% 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
Read from source at commit 0cab11a8cb56OBSERVED · 2026-10-06
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add live-coding-music-mcp --env GEMINI_API_KEY=${GEMINI_API_KEY} --env STRUDEL_SECRET_PROBE=${STRUDEL_SECRET_PROBE} -- npx -y @williamzujkowski/[email protected]
claude-desktop
{
  "mcpServers": {
    "live-coding-music-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@williamzujkowski/[email protected]"
      ],
      "env": {
        "GEMINI_API_KEY": "${GEMINI_API_KEY}",
        "STRUDEL_SECRET_PROBE": "${STRUDEL_SECRET_PROBE}"
      }
    }
  }
}
03

Exposed tools (28)

20 read · 7 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
ai_assistreadGemini-backed pattern assistance.
analyzereadAudio analysis on the currently-playing pattern.
analyze_pattern_localreadStatic analysis (events/cycle, complexity, optional BPM) without browser playback
audio_capturereadRecord audio output from the live Strudel session.
browser_windowreadInteract with the visible Strudel browser window.
composewriteGenerate, write, and play a complete pattern in one step. Auto-initializes default browser if needed.
diagnosticsreadInspect server and browser state.
edit_patternwriteMutate the current session pattern.
effectdestructiveAdd or remove a Strudel effect on the current session pattern.
export_audiowriteRecord a window of live Strudel audio and write it to a file.
export_midireadExport current pattern to MIDI file. Parses note(), n(), and chord() functions.
generate_partreadGenerate a single instrumental layer and append it to the current session pattern.
generate_rhythmreadGenerate a rhythmic pattern and append it to the current session.
get_patternreadGet current pattern code
historywriteNavigate or inspect the pattern edit history.
import_midiwriteConvert a .mid file into a playable Strudel pattern (Phase 1: literal transcription, #201).
initreadInitialize Strudel in browser
music_theoryreadMusic-theory queries.
pattern_storereadPersist patterns to disk and read them back.
playbackreadControl transport on the current session.
query_pattern_eventsreadEnumerate events the pattern would emit between two cycle indices (max 16 cycles)
sessionreadManage isolated Strudel browser sessions (multi-session, #108).
set_tempowriteSet BPM. Writes setcpm(bpm/4), assuming one bar of 4/4 per cycle.
shapereadShape the current pattern along one of three high-level dimensions.
transformwriteApply a single transform op to the current session pattern.
transpile_patternreadTranspile pattern source via StrudelEngine; returns transpiled code or syntax error
validate_pattern_localreadValidate pattern syntax against the local StrudelEngine, which runs in a sandboxed child process (no browser required)
validate_pattern_runtimereadValidate pattern with runtime error checking (monitors Strudel console for errors)
04

Trust audit

CAUTIONgrade B · trust 84/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (4 observation(s))
Network
none-observed
Shell
declared (3 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (15)

MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/__tests__/integration/GeminiService.integration.test.ts:237
apiKey: 'invalid-api-key-12345'
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
effect
Why it matters. 1 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.binary · CWE-1104
src/__tests__/unit/SafePath.test.ts
SafePath.test.ts
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.hidden_file · CWE-1104
.eslintrc.cjs
.eslintrc.cjs
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/__tests__/unit/GeminiService.test.ts:851
text: () => 'new Function("return 1")'
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/__tests__/unit/PatternSandbox.test.ts:63
['Function', `Function('return process')(); s('bd')`],
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/__tests__/unit/PatternValidator.test.ts:369
expect(result.errors).toContain('Use of eval() or Function() is not allowed');
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/__tests__/unit/PatternValidator.test.ts:373
const result = validator.validate('new Function("return s(\\"bd*4\\")")');
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/__tests__/unit/PatternValidator.test.ts:376
expect(result.errors).toContain('Use of eval() or Function() is not allowed');
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/verify-export-audio.ts:115
const escape = await service.exportAudio(page, { duration: 300, filename: '../../../../tmp/pwned' });
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/benchmarks/latency.benchmark.ts:18
import { StrudelController } from '../../StrudelController.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/benchmarks/latency.benchmark.ts:19
import { IsolatedStrudelEngine } from '../../services/IsolatedStrudelEngine.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/browser/AnalyzerFluxTimer.browser.test.ts:17
import { AudioAnalyzer } from '../../AudioAnalyzer';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/__tests__/browser/CaptureTimers.browser.test.ts:27
import { AudioCaptureService } from '../../services/AudioCaptureService';
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@google/generative-ai, @modelcontextprotocol/sdk, @tonejs/midi, google-auth-library, playwright, @types/jest, @types/node, @typescript-eslint/eslint-plugin
Why it matters. 15 dependency range(s) float
Fix. pin exact versions or ship a lockfile

Gates applied: no_behavioural_pass.

Audited 2026-10-06 · audit v0.4.1 · source sha 0cab11a8cb56full audit observations/trust-audit/mcp-server/williamzujkowski__strudel.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-060cab11a8cb56CAUTIONB84first audit
06

Questions

What is the Strudel MCP server?

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

What tools does Strudel expose?

28 in total: 20 read-only, 7 that write, and 1 that can delete or overwrite (effect). Every one is listed on this page with its risk.

Is Strudel safe to connect to an agent?

With care. The audit graded it B (84/100) and found 15 things worth knowing before you trust this server, listed below with the exact line each was found on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Strudel need?

It reads GEMINI_API_KEY and STRUDEL_SECRET_PROBE from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Strudel run?

It speaks stdio, so it runs as a local process your client starts. It is published on npm as @williamzujkowski/live-coding-music-mcp at 4.0.0.

How current is this page?

The grade is for one exact copy of the source (0cab11a8cb56), read on 2026-10-06. The repository is watched and re-audited when it changes.

Advertisement