ableton-mcp-server
by giuliobracci
README.md
# ableton-mcp-server
An [MCP](https://modelcontextprotocol.io) server that exposes **Ableton Live** to
AI agents, built as a native **Ableton Extension** on top of the official
[`@ableton-extensions/sdk`](https://ableton.github.io/extensions-sdk) (released
in beta, June 2025).
It lets an agent (Claude, etc.) **read and edit a Live set** — tracks, clips,
MIDI notes, devices/parameters, scenes — and render/import audio, all over a
local MCP endpoint.
> Status: beta. Targets Extensions SDK API `1.0.0`.
## How it works
An Ableton Extension is an `activate(context)` function that runs **inside Live's
Extension Host** — a full Node.js ≥22 process embedded in Live. This project's
`activate()` initializes the SDK and starts an **in-process MCP server over
Streamable HTTP**, bound to `127.0.0.1`. The tool handlers call straight into
Live's data model — no second process, no IPC.
```
┌─────────────── Ableton Live ───────────────┐
│ Extension Host (Node 22) │
│ activate() ─ initialize(sdk) ─ Live data │
│ │ │
│ MCP server ── Streamable HTTP ──┐ │
└────────────────────────────────────┼───────┘
│ 127.0.0.1:39001/mcp
┌───────────▼──────────┐
│ MCP client (Claude) │
└──────────────────────┘
```
Two consequences shape the design:
- **stdio is owned by the host**, so the MCP transport is HTTP, not stdio.
- **The lifecycle is inverted** — Live owns the process — so the MCP client
*connects to* an already-running endpoint rather than spawning it. The server
is only alive while Live + the extension are running; clients must tolerate it
appearing/disappearing.
## Object addressing
Tools reference Live objects by stable path strings:
| Address | Object |
|---|---|
| `song` | the song |
| `track/0` | first regular track |
| `track/0/clipslot/3` | a session clip slot |
| `track/0/clipslot/3/clip` | the clip in that slot |
| `track/0/arrangement-clip/0` | an arrangement clip |
| `track/0/device/1` | a device on a track |
| `track/0/device/1/parameter/5` | a device parameter |
| `scene/2` | a scene |
## Tools (31)
| Group | Tools |
|---|---|
| **Song** | `get_song_state`, `set_tempo` |
| **Tracks** | `list_tracks`, `get_track`, `create_midi_track`, `create_audio_track`, `duplicate_track`, `delete_track`, `rename_track`, `set_track_state` |
| **Clips** | `list_clip_slots`, `get_clip`, `create_midi_clip`, `create_arrangement_clip`, `create_audio_clip`, `delete_clip`, `set_clip_properties` |
| **MIDI** | `get_notes`, `set_notes` |
| **Devices** | `list_devices`, `insert_device`, `delete_device`, `list_parameters`, `get_parameter`, `set_parameter` |
| **Scenes** | `list_scenes`, `create_scene`, `delete_scene`, `rename_scene` |
| **Resources** | `render_pre_fx_audio`, `import_into_project` |
### What an agent can do
Read the set's state; compose (create tracks/clips, **write MIDI notes**),
edit (rename, mute/solo/arm, clip name/color/loop on-off), sound-design (insert
devices, set parameter values), and render/import audio (e.g. render a range of
an audio track to WAV).
### Known limits (from the SDK, not this server)
- **No transport/playback**: no play/stop/fire/record — the agent composes and
edits, it doesn't perform.
- **Loop points are read-only** after creation (`set_clip_properties` only
toggles `looping`).
- **No push events**: request/response only; poll to observe changes.
- `render_pre_fx_audio` renders *pre-effects* audio of an **arrangement** range.
## Setup
Requires Node ≥22.11 and a version of Ableton Live that supports extensions.
```bash
npm install
npm test # unit + real HTTP-loopback tests (no Live needed)
npm run build # bundles src/extension.ts -> dist/extension.js (CJS)
```
### Run inside Live (development)
You need the **Live Beta build that supports extensions** (from Ableton's
Centercode release page). Ableton recommends Node ≥ 24.14.1 for the toolchain;
this project also builds/tests fine on Node 22 (Live runs the extension on its
own bundled Node).
1. **Enable Developer Mode** in Live: `Preferences → Extensions → Developer
Mode`. Required — otherwise the CLI can't connect to Live.
2. **Point the CLI at Live**, either by copying `.env.example` to `.env` and
setting `EXTENSION_HOST_PATH`, or by passing `--live`:
```bash
npm start # uses .env
# or
npm start -- --live "/Applications/Ableton Live 12 Suite Beta.app"
```
`npm start` builds the extension and launches Live's Extension Host with it. On
start you'll see, in the terminal/host log:
```
[ableton-mcp] MCP server listening on http://127.0.0.1:39001/mcp
```
Config via env: `ABLETON_MCP_HOST` (default `127.0.0.1`), `ABLETON_MCP_PORT`
(default `39001`). Pass `--inspect` for VS Code debugging.
### Connect an MCP client
Because the server is already running, register it as an **HTTP** MCP server (do
not let the client spawn it). For Claude Code:
```bash
claude mcp add --transport http ableton-live http://127.0.0.1:39001/mcp
```
Or inspect it with the MCP Inspector:
```bash
npx @modelcontextprotocol/inspector
# transport: Streamable HTTP, URL: http://127.0.0.1:39001/mcp
```
Then try: `get_song_state`, `set_tempo {bpm:124}`, `create_midi_track`,
`create_midi_clip {track:"track/0", slot:0, length:4}`,
`set_notes {clip:"track/0/clipslot/0/clip", notes:[{pitch:60,startTime:0,duration:1}]}`.
### Package for distribution
```bash
npm run package # production bundle -> Ableton-MCP-0.1.0.ablx (manifest + entry)
```
A `.ablx` is the shareable/installable archive. During the SDK beta the primary
way to load an extension is Developer Mode + `npm start` above.
## Development
Built test-first with [vitest](https://vitest.dev). The architecture keeps the
host out of the test path:
- **Pure logic** (`addressing.ts`, `notes.ts`) — tested with no mocks.
- **Tools** depend only on the narrow `Live` interface and are tested against
an in-memory `FakeLive`.
- **MCP server** is tested with a real `Client`+`McpServer` over
`InMemoryTransport`, and the HTTP layer with a **real loopback** (real MCP
client over `StreamableHTTPClientTransport`).
- The only host-bound code (`live.context.ts`, `extension.ts`) is covered by the
real-Live integration test, not unit tests — the native host can't run in CI.
```
src/
addressing.ts object path parse/serialize (pure)
notes.ts MIDI note validation (pure)
live.ts the Live facade interface + DTOs
live.fake.ts in-memory Live for tests
live.context.ts real Live over the Extension Host
tools/ one file per tool group + registry
server.ts builds the McpServer from the tool registry
http.ts Streamable HTTP transport on localhost
extension.ts activate() entry point
```
## License
The Ableton Extensions SDK and CLI are © Ableton AG (see their `LICENSE.md`).
This project is provided as-is.