bandlab-mcp
Allows reading and editing your own BandLab songs by prompt, performing mix operations like track volume/pan, effects, regions, automation, and project settings.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bandlab-mcp Lower the drums by 2 dB and pan the hi-hats to the right"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bandlab-mcp
An MCP server that lets a model read and edit your own BandLab songs by prompt.
"Vokali 2 dB kıs, davulu biraz sola al, reverb'ü bypass et" → concrete mix operations → a new BandLab revision.
Read this first: there is no official BandLab API
BandLab publishes no public API, no developer program, and no OpenAPI spec. Everything here targets
the private JSON API that bandlab.com's own web app uses (https://www.bandlab.com/api/v1.3). That has
two consequences you should decide about before using this:
It can break without notice. Endpoints, field names and value ranges are undocumented and unversioned in practice. This server is written so that unknown fields survive a round-trip, but a breaking change on BandLab's side is a matter of when, not if.
It conflicts with BandLab's Terms of Use. §4.2.7 prohibits using "automated means, bots, … automated scripts, or the like" to "register Accounts, log in, add followers …, follow or unfollow other Users, send messages, post comments, or otherwise to act on your behalf", and to send "more requests … than a human can reasonably produce in the same period of time". Automating your own account on your own songs still falls under "act on your behalf". The realistic risk is account suspension. That is your call to make, not this README's.
This server is built to sit as close to the defensible side of that line as it can:
No social automation. There is no follow, unfollow, comment, message, or like tool. Those are the behaviours the Terms name explicitly, and none of them are needed to edit a mix.
Human-pace requests. Every call is serialized and spaced by
BANDLAB_MIN_INTERVAL_MS(default 1200 ms). There are no bursts and no parallel fan-out.Writes are off by default.
BANDLAB_ALLOW_WRITESmust be explicitlytrue, and even then every edit is a dry run unless the caller passesdryRun: false.Edits are non-destructive. BandLab is version-based: saving creates a new revision and the parent is preserved. Nothing this server does overwrites existing audio.
How a save becomes audible
BandLab renders mixdowns server-side. The web app watches a revision for
mixdown.status !== 'Ready' and waits to be told the render finished.
That makes one field decisive: a new revision must not carry its parent's mixdown. Copy a
finished one over and the server concludes the audio is already current, never queues a render, and
the edit stays inaudible to anyone streaming the post — the project changes, the sound does not.
prepareNewRevision() therefore drops mixdown along with the other server-owned fields.
Verified end to end on a real song: POST returned a fresh mixdown id with status: "Empty", which
went Ready about 18 seconds later, and measuring the new file against the old one showed the EQ
curve exactly as requested — 120/200 Hz down 1.7 dB relative to 800 Hz, 1.6–6.4 kHz up 0.7–1.1 dB.
Related MCP server: Ableton Copilot
How it works
BandLab stores a song as a chain of revisions. A revision is the full project tree:
revision
├── volume (master), key, description, saveType
├── metronome { bpm, signature }
├── mastering { preset }
├── auxChannels[] { id, preset, returnLevel, effects[] }
└── tracks[]
├── name, type, volume, pan, fxMix, isMuted, isSolo, colorName
├── effects[] { slug, bypass, params, automation }
├── effectsData { displayName, originalPresetId } // preset metadata, not the chain
├── auxSends[] { id, sendLevel }
├── automation { volume[], pan[] }
└── regions[] { startPosition, endPosition, gain, fadeIn, fadeOut,
pitchShift, playbackRate, sampleId }The edit loop is:
bandlab_get_mixfetches a revision and renders it as compact text, so the model reasons over levels and effects rather than a huge JSON blob.The model turns the prompt into typed operations (
set_track_volume,add_effect,move_region, …).bandlab_edit_mixapplies them purely — the fetched revision is cloned, never mutated — and returns a before/after diff.Only on a second call with
dryRun: falseis a new revision POSTed.
Setup
npm install
npm run buildCredentials
Three modes. The first two reuse a session you created by logging in yourself, which keeps the server out of §4.2.7's "automated login".
Mode A — refresh token (recommended, self-renewing).
Log in to bandlab.com in your browser.
DevTools → Application → Cookies →
https://www.bandlab.com→ copy therefreshTokenvalue.Put it in
BANDLAB_REFRESH_TOKEN.
The server exchanges it at BandLab's identity server
(https://accounts.bandlab.com/oauth/connect/token, public client bandlab_web) for a 24-hour access
token, caches it in ~/.bandlab-mcp/session.json (mode 0600), and renews it automatically. You paste
this once.
Note that the v1.3 POST /authorizations route rejects these tokens — they are OAuth refresh
tokens and only the identity server accepts them. The server tries OAuth first and falls back to the
legacy route, so either kind of token works.
Mode B — session bearer token (quick, expires in 24 h).
DevTools → Network → any api/v1.3 request → Request Headers → copy the whole
Authorization: Bearer eyJ… value into BANDLAB_SESSION_KEY (the Bearer prefix is stripped for
you). There is nothing to renew it with, so when it expires the server tells you to paste a fresh one.
Mode C — email and password. The server calls POST /authorizations itself. The password is never
written to disk, but programmatic login is precisely what §4.2.7 names, so prefer A or B.
cp .env.example .env # then fill in whichever mode you choseVerify against your real account
npm run verify:liveRead-only. It checks every assumption this codebase makes — the shape of tracks[], the real ranges of
volume and pan, which effect slugs your projects use — and prints which ones do not hold.
Register with Claude Code
claude mcp add bandlab --scope user -- node /absolute/path/to/bandlab-mcp/dist/index.jsNo --env flags are needed: the server loads .env from its own package directory, resolved against
the module rather than the working directory, because an MCP client spawns it from wherever it likes.
Variables already present in the environment take precedence, so claude mcp add --env KEY=value still
overrides the file when you want it to.
--scope user makes it available in every project. Use --scope project instead to commit a
.mcp.json for a team — but then keep credentials in the environment, not in that file.
Verify with claude mcp list; the entry should report ✔ Connected. Newly added servers are picked up
when Claude Code next starts, so restart it before expecting the bandlab_* tools to appear.
Tools
Tool | Purpose |
| Confirm the session and get your user id |
| Your songs |
| A song's revision history (its undo stack) |
| Render one revision: tracks, levels, pan, effects, regions |
| Apply mix operations — dry run by default |
| The harvested effect catalogue: slugs, parameters, observed ranges |
| API base, write state, pacing, inferred value ranges |
| Escape hatch for endpoints not yet wrapped |
Audio upload is not a tool yet but is solved and scripted:
node scripts/upload-audio.mjs song.wav returns a sample id you can build a song around. The protocol
and the v2.0 auth quirk behind it are written up in docs/effects-reference.md.
Mix operations
Group | Operations |
Levels |
|
Routing |
|
Effects |
|
Arrangement |
|
Project |
|
Automation |
|
Tracks are addressable by id, by name (case-insensitive, partial allowed), or by 1-based number. An ambiguous name is refused with the list of matches rather than guessed at.
Effect slugs
BandLab assembles its effect list inside a WASM audio engine at runtime, so there is no endpoint to
ask and the UI names do not map onto slugs (pedalThreeBandEq2 is threeBandEq,
pedalMultibandCompressor is multibandComp2). scripts/harvest-effects.mjs therefore reads real
published projects and the community preset library and records only what it actually saw:
node --env-file-if-exists=.env scripts/harvest-effects.mjs 50That writes docs/effects-catalogue.json, which bandlab_list_effects
serves and bandlab_edit_mix validates against — an unlisted slug is refused rather than written,
because BandLab accepts any JSON and a bad slug lands in the project silently instead of erroring.
Pass allowUnverifiedEffects: true to override.
What is verified, and what is not
Verified live against www.bandlab.com/api/v1.3 with a real authenticated session:
the API version is reachable and current (
/genresreturns real data; v1.5/v1.7/v1.9 are 404)POST /authorizationsacceptsprovider: "Password"andprovider: "Token"(refresh)auth is OpenID Connect from
https://accounts.bandlab.com/oauth— session JWTs last 24 hpublic reads work unauthenticated;
/revisions/{id}and/search/*require a bearer tokentracks[]is a real DAW tree:volume,pan,isMuted,isSolo,name,effects[],regions[],auxSends[],automation. The community spec types it asAudioSample[]; that is wrong.effects[]is the signal chain;effectsDatais only preset provenance (see docs/effects-reference.md)real effect slugs and param schemas:
compressor,expGate,deEsser,threeBandEq,bossGE7,simpleStudioReverb,reverbHybridcanEditcorrectly reportsfalseon revisions you do not own, and the server refuses those writes
Two corrections the live data forced:
auxSends[].sendLevelis lowercase. The spec saysSendLevel; writing that adds a dead field.Live revisions carry
volume(master),saveType,trackGroups,samplerKits,fxMix, and regiongain/fadeIn/fadeOut— none of which appear in the spec. All are modelled now.
POST /revisions is verified. A full round-trip was run against a real owned song: fetch revision
→ mute a track, −2 dB on another, aux send 0.25, add a compressor → POST → read back. Every change
persisted, isPublic: false was honoured, and the parent revision was left untouched. The payload that
prepareNewRevision() builds — the whole revision minus id, postId, createdOn, modifiedOn,
counters and stamp, with parentId pointing at the parent — is accepted as-is.
Still unverified:
the top of the
volumerange:1.995was observed, consistent with a0..2scale, but unconfirmed.audio upload: no sample-upload endpoint appears among the 123 known endpoints, so adding new audio is out of scope until that path is found. Editing existing audio is unaffected.
bandlab_capabilities reports the inferred ranges at runtime so they can be checked rather than trusted.
Development
npm run typecheck
npm test # 24 unit tests over the pure edit engine
npm run verify # build + testThe edit engine (src/mix.ts) is pure and has no network dependency, which is why it is the part under
test. The HTTP and auth layers are thin by design.
License
MIT.
Available Tools
8 toolsbandlab_capabilitiesServer capabilities and limitsARead-only
Reports the API base, whether writes are enabled, the request pacing, and the inferred value ranges the edit engine enforces. Useful for diagnosing a refusal.
Inputs: no named parameters.
bandlab_edit_mixEdit a mixA
Applies mix operations to a revision. Defaults to a dry run that shows the diff without sending anything. With dryRun=false it saves a NEW revision (the original is never overwritten — BandLab keeps every version).
Inputs: ops (required), revisionId (required), dryRun, isPublic, +2 more.
bandlab_get_mixRead a mixARead-only
Fetches one revision and renders its tracks, levels, panning, effects and regions as compact text. This is what you read before proposing an edit.
Inputs: revisionId (required), raw.
bandlab_list_effectsEffect catalogueARead-only
Lists BandLab effect slugs and their parameters, harvested from real published projects. Consult this before add_effect or set_effect_params: BandLab has no effects endpoint, slugs are undocumented, and a slug that is not listed here is one this server cannot vouch for.
Inputs: query.
bandlab_list_revisionsList revisions of a songARead-only
Lists the revision history of a song, oldest first (verified against the live API). BandLab is version-based: every save is a revision, so this is the undo history.
Inputs: songId (required), limit.
bandlab_list_songsList my songsARead-only
Lists songs belonging to the authenticated user. Use the returned song id with bandlab_list_revisions.
Inputs: limit.
bandlab_raw_requestRaw API requestA
Escape hatch for endpoints this server does not wrap yet. The BandLab API is undocumented, so this is how you explore it. GET always allowed; other methods require writes to be enabled.
Inputs: path (required), body, query, method.
bandlab_whoamiWho am I on BandLabARead-only
Returns the authenticated BandLab profile (id, username, counters). Call this first to confirm the session works and to get the user id other tools need.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each tool targets a distinct concern: identity, song listing, revision history, mix reading, mix editing, effect metadata, API capabilities, and raw fallback. The only potential overlap is raw_request, but it is explicitly framed as an escape hatch rather than a competing operation.
Most tools follow a consistent bandlab_<verb>_<noun> pattern (list_songs, list_revisions, edit_mix, get_mix, list_effects). A few names deviate (whoami, capabilities, raw_request), but the shared prefix and clear verb/noun semantics keep the set predictable.
Eight tools is a well-scoped size for a BandLab-focused MCP server. Each tool supports a recognizable workflow from authentication to revision exploration to mix editing, without redundancy or bloat.
The core workflow is covered: identify user, list songs, inspect revisions, read a mix, edit a mix, and look up effect parameters. The main gaps are broader BandLab operations like song creation/deletion or download, but the raw_request escape hatch mitigates those and the server appears intentionally scoped to mix editing.
Maintenance
Related MCP Connectors
Compose, mix, master and export in Logic Pro, REAPER or Ableton Live by talking to an AI engineer.
AI mixing and mastering in the chat: check a song, mix your stems, change the mix in plain words.
AI mixing and mastering: analyze your mixes, run DSP autofix, render stems, and master tracks.
Browser DAW for AI assistants: build multitrack songs with MIDI, effects, stems and generation.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI-powered music generation through natural language commands, supporting inspiration and custom modes with dual song outputs.1MIT
- AlicenseBqualityDmaintenanceEnables AI-powered music production in Ableton Live through natural language, with tools for composition, arrangement, mixing, and sound design.52MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI song generation, covers and remixes, stem separation, voice conversion, and audio editing directly within your music account.1MIT
- AlicenseNot gradedqualityBmaintenanceEnables Claude to co-produce music in a self-hosted browser DAW by creating and editing patterns, chords, basslines and melodies, arranging and automating tracks, mixing with effects and spatial placement, analyzing and editing samples, rendering mixes with mastering feedback, and exporting MIDI and stems — all reflected live in the studio.MIT