Content
# ableton-agent
A Bun workspace with two packages:
- [`packages/ableton-agent`](packages/ableton-agent) — the TypeScript library (`Live`/`Song`/`Track`/`Clip`/`Device`) plus the two OSC transports it talks to: the Max for Live `bridge.js` device (generic get/set/call) and the Python `AbletonAgent` remote script (browsing, loading, MIDI notes).
- [`packages/ableton-agent-mcp`](packages/ableton-agent-mcp) — an MCP server exposing the library as tools for an LLM agent, following the DAW tool spec in `.claude/references/daw_mcp_tool_specs.md` where the Live Object Model supports it: session state, tempo/signature/key, transport, tracks & mixer, devices & parameters, clips, and low-level MIDI note editing.
To install dependencies:
```bash
bun install
```
Run a package's script from the root with `--filter`, e.g.:
```bash
bun run --filter ableton-agent test
bun run --filter ableton-agent check-agent
bun run --filter ableton-agent-mcp start
```
## Running the MCP server
The server needs a running Ableton Live session to talk to, via at least one of:
- **The Max for Live bridge** — load [`packages/ableton-agent/max/ableton-agent.amxd`](packages/ableton-agent/max/ableton-agent.amxd) onto any track in your Live set. It wraps `bridge.js` and listens on fixed ports 9000/9001. Handles everything except browsing, loading, and MIDI note editing.
- **The AbletonAgent remote script** — symlink or copy [`packages/ableton-agent/remote-script/AbletonAgent`](packages/ableton-agent/remote-script/AbletonAgent) into Ableton's User Library Remote Scripts folder (e.g. `~/Music/Ableton/User Library/Remote Scripts/AbletonAgent` on macOS), then enable **AbletonAgent** as a Control Surface in Live's Link/Tempo/MIDI preferences (ports 9010/9011). Required for `list_instruments`/`list_browser_category`/`browse`/`load_from_browser` and the `write_midi_notes`/`get_midi_notes`/`transpose_notes` family — the Max bridge doesn't implement those. Live only loads remote scripts at startup, so restart Live (or toggle the control surface off/on) after editing `__init__.py`.
With one or both running, sanity-check connectivity:
```bash
bun run --filter ableton-agent check-agent
```
Then start the MCP server:
```bash
bun run --filter ableton-agent-mcp start
```
It speaks MCP over stdio, so it's meant to be launched by an MCP client rather than left running in a terminal. To wire it into Claude Desktop, add it to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"ableton-agent": {
"command": "bun",
"args": ["run", "/absolute/path/to/ableton-agent/packages/ableton-agent-mcp/index.ts"]
}
}
}
```
Both transports default to fixed local ports; override with env vars if you've changed either side:
| Env var | Default | Transport |
| --- | --- | --- |
| `ABLETON_MAX_ADDRESS` | `127.0.0.1` | Max bridge |
| `ABLETON_MAX_LOCAL_PORT` | `9001` | Max bridge |
| `ABLETON_MAX_REMOTE_PORT` | `9000` | Max bridge |
| `ABLETON_AGENT_ADDRESS` | `127.0.0.1` | AbletonAgent |
| `ABLETON_AGENT_LOCAL_PORT` | `9011` | AbletonAgent |
| `ABLETON_AGENT_REMOTE_PORT` | `9010` | AbletonAgent |
## Testing
`bun test` (or the commands above) runs two kinds of tests:
- Fake-backed tests (`live.test.ts`, `packages/ableton-agent-mcp/index.test.ts`) exercise the library and every MCP tool against an in-memory stand-in for Ableton (`testSupport/fakeAbleton.ts`) that speaks the real OSC wire protocol. These always run and never touch a real Live session.
- `packages/ableton-agent-mcp/index.real.test.ts` exercises every MCP tool against a **real, running Ableton Live session** — with `max/bridge.js` and the `AbletonAgent` remote script both enabled. There's no opt-in flag and no skipping: every test always attempts its real call and reports a genuine pass or fail. **This means plain `bun test` requires Ableton to be open, and will start real, audible playback.** If Ableton isn't reachable, or a specific backend/feature isn't available, the affected tests fail with a message explaining what's missing — see `packages/ableton-agent/check-agent.ts` to debug connectivity.
All mutations are confined to a scratch MIDI track it creates and deletes; global properties it touches (tempo, time signature, key, playhead) are saved and restored.
This project was created using `bun init` in bun v1.3.14. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.