supercollider-mcp
An MCP server that gives an LLM a synthesis engine, a feedback loop, and ears.
The AI boom has influenced basically every generative/creative industry, music included. Tools like Suno are impressive, but they hand you a finished track. What if you want to iterate on the product and get more control of what comes out? LLMs are good at producing code, but they are not designed to produce sound directly. So why not ask an LLM to produce code that produces sound? There exist tools that fit this description. SuperCollider is an audio platform that allows you to write code to produce sound.
SuperCollider is an open-source platform for audio synthesis and algorithmic composition. It consists of two parts: scsynth (the audio server) and sclang (the SuperCollider language). Just generating code and playing it would be impressive, but I wanted to add a feedback loop so that the LLM can get feedback on its own composition. This is where supercollider-mcp comes into play.
MCP (Model Context Protocol) is an open protocol for AI models to call tools in external processes. supercollider-mcp puts SuperCollider behind the protocol so that the LLM can render a score, measure the result, and play it for the composer, all from a chat. The model writes Python against the supriya bindings rather than sclang, which keeps every SynthDef, sequencer helper, and analysis call in one language.
What it can make
Every clip below was composed by Claude Code through the server, from a chat prompt, with no audio editing afterwards. They are short on purpose: each one is a single idea, rendered, measured, and adjusted a few times.
| Clip | What it is | Why a model can do it |
|---|---|---|
| Choir | Eight chords in D minor, each sung by 30 to 70 synthesized formant voices with random detune, vibrato, and onset, in one shared hall | One chord every eight seconds. The “crowd” is a loop that jitters the same voice many times |
| Trailer | Sub drone, string ostinato, timpani, a riser into a braam and boom drop, reverb tail | A fixed arc (intro, build, drop, outro) with a named instrument for each beat of it |
| Lofi | Four jazzy seventh chords on a loop, swung drums, a sparse pentatonic melody, filtered noise for vinyl | A two-bar loop where imperfection is the style, so timing and level jitter help instead of hurt |
| Dub techno | Four-on-the-floor kick, sidechained sub, one minor seventh stab echoing in dotted eighths, a filter opening over 14 bars | Repetition plus one slow process. The whole piece is a single chord |
| Phase | One 12-note cell played by two plucked voices, the second running 1/96 faster, so they drift apart and lock into new rhythms | Steve Reich’s phasing idea is an algorithm. The score is a while loop |
Here is the whole “composition” behind the phase clip. The second call to voice is the piece:
= # E minor pentatonic
= 0.125 # 16ths at 120 bpm
, = , 0
=
+=
+= 1
The full scripts live in the repository under examples/.
What is easy, and what is not
A pattern emerged while making these. Language models are not good at composing a song in the sense of a melody with a harmonic story, a bridge, and a payoff. That still needs a person. What they are good at is picking a small set of rules and executing them with total consistency, and there are whole genres built exactly that way:
- Ambient, drone, and choir washes: a slow chord arc plus texture. The craft is in the sound, not the notes.
- Minimalism and process music: one cell and one process (phasing, additive layering, a filter sweep).
- Lofi and dub techno: a short loop where the interest comes from imperfection, space, and one thing changing slowly.
- Trailer cues: a formula with a named instrument for every step.
The ordering is not accidental. The lower the harmonic and melodic complexity, the better the result, because what remains is sound design and arrangement, and both of those can be measured. Genres that need a real voice, jazz voice leading, or acoustic realism (pop, jazz, orchestral) are where the tool stops today.
How the server is built
The MCP server uses FastMCP. It is a Python library that turns decorated functions into MCP tools. Each tool is a plain Python function, and the docstring becomes the tool description that the LLM reads to decide when and how to use it.
=
"""Execute Python/supriya code against the live scsynth server."""
=
=
return
=
return f
The code the model writes runs in a prepared context: a library of 37 SynthDefs (pads, basses, a drum kit, strings, brass, leads, guitars, transition effects), a sequencer that expands pattern strings like "x..x..x." into events with swing and jitter, a sampler, and a master bus with a global reverb, a sidechain pump, and a brickwall limiter so every render is peak-safe by default.
Tools
| Tool | Description |
|---|---|
sc_play(code) | Run Python/supriya code on the live server |
sc_stop | Stop all sounds, signal song threads to exit |
sc_render(code, duration, seed, genre) | Non-realtime render to WAV at 50 to 150x realtime; returns a one-line analysis summary |
sc_analyze(path, genre, windows) | Measure a render: loudness, dynamics, transients, tempo, spectrum, stereo, key, judged against a genre profile |
sc_prepare_reference / sc_compare | Turn a reference track into a comparable clip and score a render’s similarity to it |
sc_log | Read scsynth output and exec errors |
sc_boot / sc_quit / sc_ping | Server lifecycle |
save_song / load_song / list_songs | Song library |
save_pattern / load_pattern / list_patterns | Pattern snippets |
The workflow
The model can’t hear, so it gets feedback two ways: one loop for whether the code is correct, and one for whether it sounds good.
The correctness loop
The LLM treats sc_play and sc_log as a pair: play, immediately read the log for exceptions and engine warnings, fix what is found, and resend. This iterates until the code runs clean.
The quality loop
sc_log catches what is broken, but not what sounds bad. sc_analyze fills that gap. It reads a rendered file and reports measurable proxies: integrated loudness, true peak, dynamic range, crest factor, tempo, spectral balance per band, stereo width, mono compatibility, and key. Each number is judged against a target profile for the genre the model says it is making, so a quiet, wide-dynamics trailer is not flagged the way a quiet techno loop is. The lofi clip above went through three rounds of this: the first render was nearly mono and the bass swamped the chords, and the numbers said so.
sc_analyze can’t replace taste, but it catches the technical defects a person would flag and lets the model iterate toward known-good numbers. A render takes well under a second, so a round trip is cheap.
Building a song
Songs are built over many iterations where one iteration is one conversation turn. The model writes code, renders it, reads the analysis back, and proposes the next change. Then the composer listens and decides which direction to take. The resulting workflow is less “AI-generated music” and more “AI-assisted composition” with very fast iteration cycles. The model handles the code synthesis, and the musical direction comes from prompting.
Summary
Give a model a synthesis engine, a feedback loop, and ears, and code generation turns into music composition. Keep the musical idea small and the model will execute it well; bring the big idea yourself.