# remix-mcp > Control Ableton Live with AI via MCP ## Acknowledgements remix-mcp is built on the shoulders of giants. ### AbletonOSC This project would not be possible without [AbletonOSC](https://github.com/ideoforms/AbletonOSC) by [Daniel Jones (ideoforms)](https://github.com/ideoforms). AbletonOSC is the Python Remote Script that runs inside Ableton Live and exposes the Live Object Model via OSC, enabling external control of the DAW. ### Dependencies #### Core * [rmcp](https://github.com/anthropics/rmcp) - Rust implementation of the Model Context Protocol * [rosc](https://github.com/klingtnet/rosc) - OSC (Open Sound Control) library for Rust * [tokio](https://tokio.rs) - Async runtime for Rust #### CLI * [clap](https://github.com/clap-rs/clap) - Command line argument parser * [indicatif](https://github.com/console-rs/indicatif) - Progress bars and spinners * [console](https://github.com/console-rs/console) - Terminal styling #### Serialization * [serde](https://serde.rs) - Serialization framework * [schemars](https://github.com/GREsau/schemars) - JSON Schema generation #### Error handling * [color-eyre](https://github.com/eyre-rs/eyre) - Colorful error reports * [thiserror](https://github.com/dtolnay/thiserror) - Derive macro for errors #### Testing * [insta](https://insta.rs) - Snapshot testing * [rstest](https://github.com/la10736/rstest) - Parameterized tests ## Architecture How remix-mcp connects AI assistants to Ableton Live. ### Overview ``` Claude/Client <--stdio/JSON-RPC--> remix-mcp <--UDP/OSC--> AbletonOSC <--> Ableton Live ``` remix-mcp is the bridge between MCP clients (like Claude) and Ableton Live. It translates MCP tool calls into OSC messages that AbletonOSC understands. ### Components #### MCP Server (remix-mcp) A Rust binary that implements the Model Context Protocol: * **Protocol**: JSON-RPC over stdio * **Runtime**: Tokio async * **Framework**: `rmcp` crate The server exposes 266 tools that Claude can call. Each tool: 1. Validates parameters 2. Sends OSC messages to AbletonOSC 3. Waits for and parses responses 4. Returns results to Claude #### AbletonOSC A Python Remote Script that runs inside Ableton Live: * **Location**: Ableton's Remote Scripts folder * **Protocol**: UDP/OSC on ports 11000 (receive) and 11001 (send) * **API**: Exposes Ableton's Live Object Model AbletonOSC translates OSC messages into calls to Ableton's Python API. #### Why OSC? Ableton's Python API (Live Object Model) runs in a sandboxed interpreter inside Ableton. External processes cannot call it directly. OSC (Open Sound Control) over UDP provides: * **Low latency**: Fast enough for real-time control * **Loose coupling**: No direct process communication needed * **Standard protocol**: Well-supported in music software ### Data Flow #### Example: Set Tempo ``` 1. User: "Set tempo to 128 BPM" 2. Claude: Calls set_tempo(tempo: 128) 3. MCP: JSON-RPC request to remix-mcp 4. remix-mcp: Sends OSC /live/song/set/tempo 128.0 5. AbletonOSC: Receives, calls song.tempo = 128.0 6. Ableton: Tempo changes 7. remix-mcp: Returns success 8. Claude: "Done! Tempo is now 128 BPM" ``` #### Example: Query ``` 1. User: "What's the current tempo?" 2. Claude: Calls get_tempo() 3. remix-mcp: Sends OSC /live/song/get/tempo 4. AbletonOSC: Reads song.tempo, sends response 5. remix-mcp: Parses 120.0 from response 6. Claude: "The tempo is 120 BPM" ``` ### Code Structure ``` src/ ├── main.rs # CLI entry point ├── lib.rs # Library exports ├── server.rs # MCP ServerHandler ├── error.rs # Error types ├── installer.rs # AbletonOSC installer ├── osc/ │ ├── client.rs # Async UDP OSC client │ ├── message.rs # OSC message helpers │ └── response.rs # Response parsing ├── tools/ │ ├── transport.rs # Playback tools │ ├── tracks.rs # Track tools │ ├── clips.rs # Clip tools │ ├── scenes.rs # Scene tools │ ├── devices.rs # Device tools │ ├── song.rs # Song tools │ ├── view.rs # Selection tools │ ├── cue_points.rs │ └── browser.rs # Browser tools └── types/ ├── params.rs # Data types ├── tool_params.rs # Tool parameters └── ids.rs # ID types ``` ### OSC Protocol OSC addresses follow the pattern: `/live/{object}/{action}/{property}` | Pattern | Purpose | Example | | -------------------------- | ------- | ------------------ | | `/live/song/start_playing` | Action | Start playback | | `/live/song/get/tempo` | Getter | Read tempo | | `/live/song/set/tempo` | Setter | Change tempo | | `/live/track/get/volume` | Indexed | Get track N volume | ### Error Handling | Error | Cause | Recovery | | ------------------ | ------------------- | ------------------- | | `InvalidParameter` | Bad input | Fix parameters | | `InvalidResponse` | Unexpected OSC data | Check Ableton state | | `Timeout` | No response (5s) | Check connection | | `Network` | UDP/socket error | Check ports | ### Performance * **Latency**: \~5-20ms per operation (UDP roundtrip) * **Throughput**: Hundreds of operations per second * **Memory**: \~10MB typical * **CPU**: Minimal (async I/O) ### Security * **Local only**: Binds to 127.0.0.1 * **No auth**: Trusts localhost connections * **Sandboxed**: Only affects Ableton, no system access ## Configuration ### Claude Desktop Add remix-mcp to your Claude Desktop configuration: #### Location | Platform | Config Path | | -------- | ----------------------------------------------------------------- | | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | #### Basic Configuration ```json { "mcpServers": { "ableton": { "command": "uvx", "args": ["remix-mcp"] } } } ``` #### Using Binary Directly If you installed the binary manually: ```json { "mcpServers": { "ableton": { "command": "/path/to/remix-mcp" } } } ``` ### Claude Code Add the server with a single command: ```bash claude mcp add ableton -- uvx remix-mcp ``` Or with a local binary: ```bash claude mcp add ableton -- /path/to/remix-mcp ``` List configured servers: ```bash claude mcp list ``` Remove a server: ```bash claude mcp remove ableton ``` ### CLI Commands remix-mcp provides several commands: ```bash # Start MCP server (default, used by Claude) remix-mcp serve # Install AbletonOSC Remote Script remix-mcp install # Force reinstall remix-mcp install --force # Check installation status remix-mcp status # Show help remix-mcp --help ``` ### Environment Variables Currently, remix-mcp uses hardcoded defaults for OSC communication: | Setting | Default | Description | | ------------ | --------- | -------------------------------- | | Send Port | 11000 | Port to send OSC to Ableton | | Receive Port | 11001 | Port to receive OSC from Ableton | | Host | 127.0.0.1 | Localhost only | | Timeout | 5s | Response timeout | :::note Custom port configuration is planned for a future release. ::: ## Contributing Guidelines for contributing to remix-mcp. ### Development Setup #### Prerequisites * Rust (latest stable) * Ableton Live (for integration tests) * pnpm (for docs) #### Clone & Build ```bash git clone --recursive https://github.com/christopherwxyz/remix-mcp cd remix-mcp cargo build ``` The `--recursive` flag is important to include the AbletonOSC submodule. #### Running Tests ```bash # Unit tests (no Ableton required) cargo test # Faster test runner cargo nextest run # Integration tests (requires Ableton + AbletonOSC) cargo test --test integration -- --ignored --test-threads=1 ``` #### Linting ```bash cargo clippy cargo fmt cargo deny check ``` ### Adding a New Tool Tools use rmcp's procedural macros. Here's the pattern: #### 1. Define Parameters (if needed) In `src/types/tool_params.rs`: ```rust #[derive(Debug, Deserialize, JsonSchema)] pub struct MyToolParams { #[schemars(description = "Description of the parameter")] pub my_param: i32, } ``` #### 2. Implement the Tool In the appropriate file under `src/tools/`: ```rust #[tool_router(router = category_router, vis = "pub")] impl AbletonServer { #[tool(description = "Description of what the tool does")] pub async fn my_tool( &self, Parameters(params): Parameters, ) -> Result { // Send OSC and handle response self.osc.send("/live/path", vec![ OscType::Int(params.my_param) ]).await?; Ok("Success".to_string()) } } ``` #### 3. Register the Router In `src/server.rs`, ensure the router is composed: ```rust router.merge(category_router()); ``` ### Code Style * Use `rustfmt` defaults * Follow Clippy recommendations * Prefer `thiserror` for error types * Use `tracing` for logging * Write tests for new functionality ### OSC Communication Patterns #### Send Only (Actions) ```rust self.osc.send("/live/song/start_playing", vec![]).await?; ``` #### Query Single Value ```rust let tempo: f32 = self.osc.query("/live/song/get/tempo", vec![]).await?; ``` #### Query Multiple Values ```rust let packets = self.osc.query_all("/live/track/get/all", vec![]).await?; ``` ### Error Handling Use appropriate error variants: ```rust // Bad user input Error::InvalidParameter("track_index must be >= 0".into()) // Unexpected response Error::InvalidResponse("Expected float, got string".into()) // Connection issues Error::Timeout Error::Network(e) ``` ### Documentation When adding tools, update: 1. Tool count in `CLAUDE.md` 2. Tool documentation in `docs/pages/tools/` 3. Examples if applicable ### Pull Request Process 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Run tests and linting 5. Submit a PR with a clear description ### Questions? Open an issue on [GitHub](https://github.com/christopherwxyz/remix-mcp/issues). ## Examples Practical examples of using remix-mcp with Claude to create music in Ableton Live. ### Building a track from scratch ``` You: Create a chill lo-fi beat at 85 BPM Claude: I'll set up a relaxed lo-fi track for you... [Sets tempo to 85 BPM] [Creates 3 tracks:] - Keys (Drift synth with warm pad) - Bass (low sine bass) - Drums (laid-back boom bap pattern) [Fires all clips, starts playback] ``` ### Melodies ``` You: Create a C major scale Claude: [Creates MIDI track, loads Drift, adds notes C-D-E-F-G-A-B-C] ``` ``` You: Create a I-V-vi-IV progression in C major Claude: [Creates track with C, G, Am, F chords over 4 bars] ``` ### Drums ``` You: Create a basic house beat at 120 BPM Claude: [Creates kick on 1-2-3-4, snare on 2-4, hi-hats on 8ths] ``` ``` You: Add some swing to the hi-hats Claude: [Adjusts timing to add groove] ``` ### Effects ``` You: Add reverb and delay to the selected track Claude: [Loads Reverb and Delay audio effects to the track] ``` ### Synthesizers vs samplers When creating MIDI tracks, Claude loads **Drift** by default (a synthesizer that generates sound immediately). | Type | Examples | Sounds immediately? | | ------------ | ------------------------ | ------------------- | | Synthesizers | Drift, Analog, Wavetable | Yes | | Samplers | Simpler, Sampler | No (needs samples) | :::warning If you're not hearing sound from a MIDI track, check if the instrument is a sampler that needs samples loaded. ::: ### Session view vs arrangement view Ableton has two main views (press **Tab** to toggle): | Session view | Arrangement view | | ----------------------------- | ---------------- | | Clip grid for launching clips | Linear timeline | | Great for jamming | Great for mixing | remix-mcp creates clips in **Session View** by default. ### Ideas to try * "Create a 4-chord EDM progression and add a sidechain compressor" * "Build a minimal techno loop with a hypnotic bassline" * "Create a jazz chord progression with voice leading" * "Duplicate the current scene and transpose all clips up a 5th" ## Getting started Remix is a Rust MCP (Model Context Protocol) server that enables AI assistants to control Ableton Live via OSC. ### Prerequisites * **Ableton Live** (Suite, Standard, or Intro) * **Claude Desktop** or **Claude Code** * One of: * [uv](https://docs.astral.sh/uv/) (recommended) * Rust toolchain for building from source ### Quickstart #### 1. Install Remix The easiest way is via uv: ```bash uvx remix-mcp install ``` Or download a pre-built binary from [GitHub Releases](https://github.com/christopherwxyz/remix-mcp/releases). #### 2. Install AbletonOSC Run the installer: ```bash remix-mcp install ``` Then enable it in Ableton: 1. Restart Ableton Live 2. Open **Preferences** (`Cmd+,` / `Ctrl+,`) 3. Go to **Link/Tempo/MIDI** 4. Under **Control Surface**, select **AbletonOSC** You should see in the status bar: ``` AbletonOSC: Listening for OSC on port 11000 ``` #### 3. Configure Your AI Client :::steps ##### Claude Desktop 1. Open Claude Desktop Settings > Developer 2. Click "Edit Config" to open `claude_desktop_config.json` 3. Add the server: ```json { "mcpServers": { "ableton": { "command": "uvx", "args": ["remix-mcp"] } } } ``` 4. Restart Claude Desktop ##### Claude Code ```bash claude mcp add ableton -- uvx remix-mcp ``` ::: ### Verify Installation Open Claude and try: > "Get the current tempo from Ableton" If connected, Claude will respond with the current tempo. If not, see [Troubleshooting](/troubleshooting). ### Next Steps * [Examples](/examples) - See what you can build * [Tools Reference](/tools) - Browse all 266 tools * [Architecture](/architecture) - Understand how it works ## Installation ### Installing remix-mcp #### Via uv (Recommended) [uv](https://docs.astral.sh/uv/) is a fast Python package installer that can run Rust binaries: ```bash uvx remix-mcp install ``` This downloads and runs the latest release automatically. #### Download Binary Download pre-built binaries for your platform from [GitHub Releases](https://github.com/christopherwxyz/remix-mcp/releases): * **macOS (Apple Silicon)**: `remix-mcp-aarch64-apple-darwin.tar.gz` * **macOS (Intel)**: `remix-mcp-x86_64-apple-darwin.tar.gz` * **Linux**: `remix-mcp-x86_64-unknown-linux-gnu.tar.gz` * **Windows**: `remix-mcp-x86_64-pc-windows-msvc.zip` Extract and add to your PATH. #### Build from Source Requires [Rust](https://rustup.rs/): ```bash git clone --recursive https://github.com/christopherwxyz/remix-mcp cd remix-mcp cargo build --release ``` The binary will be at `target/release/remix-mcp`. ### Installing AbletonOSC AbletonOSC is a Remote Script that runs inside Ableton Live, exposing its API over OSC. #### Automatic Installation ```bash remix-mcp install ``` This copies the AbletonOSC folder to your Ableton Remote Scripts directory: | Platform | Path | | -------- | -------------------------------------------------------------- | | macOS | `~/Music/Ableton/User Library/Remote Scripts/` | | Windows | `%USERPROFILE%\Documents\Ableton\User Library\Remote Scripts\` | #### Enable in Ableton 1. **Restart** Ableton Live (required after installing scripts) 2. Open **Preferences** (`Cmd+,` / `Ctrl+,`) 3. Navigate to **Link/Tempo/MIDI** 4. Under **Control Surface**, select **AbletonOSC** :::tip Look for `AbletonOSC: Listening for OSC on port 11000` in the status bar to confirm it's working. ::: #### Check Status Verify installation: ```bash remix-mcp status ``` #### Reinstall Force reinstall if needed: ```bash remix-mcp install --force ``` ### Network Ports remix-mcp communicates with AbletonOSC over UDP: | Port | Direction | Purpose | | ----- | -------------------- | ----------------- | | 11000 | remix-mcp -> Ableton | Send OSC commands | | 11001 | Ableton -> remix-mcp | Receive responses | Ensure these ports are not blocked by firewalls or used by other applications. ## Troubleshooting Common issues and their solutions. ### Connection Issues #### Connection Timeout **Symptoms**: Claude reports timeout or cannot connect to Ableton. **Solutions**: 1. **Check Ableton is running** - The MCP server needs Ableton Live open and running. 2. **Verify AbletonOSC is enabled**: * Open Preferences (`Cmd+,` / `Ctrl+,`) * Go to Link/Tempo/MIDI * Ensure AbletonOSC is selected under Control Surface 3. **Check ports are free** - Ports 11000 and 11001 must not be used by other apps: ```bash # macOS/Linux lsof -i :11000 lsof -i :11001 # Windows netstat -ano | findstr :11000 ``` 4. **Restart both apps** - Sometimes a clean restart of both Ableton and Claude fixes connection issues. #### AbletonOSC Not in Control Surface List **Symptom**: AbletonOSC doesn't appear in the dropdown. **Solutions**: 1. **Run the installer**: ```bash remix-mcp install ``` 2. **Restart Ableton** - Required after installing new Remote Scripts. 3. **Check installation**: ```bash remix-mcp status ``` 4. **Verify the path** - Ensure the Remote Scripts folder exists: * macOS: `~/Music/Ableton/User Library/Remote Scripts/AbletonOSC/` * Windows: `%USERPROFILE%\Documents\Ableton\User Library\Remote Scripts\AbletonOSC\` ### Audio Issues #### No Sound from MIDI Tracks **Symptom**: MIDI notes are created but no audio plays. **Causes & Solutions**: 1. **Empty sampler loaded** - Samplers need samples to make sound: ``` # Use a synth instead load_default_instrument ``` 2. **Track not armed** - The track may need to be armed for monitoring: ``` arm_track(track_index) ``` 3. **Volume at zero** - Check track and master volume: ``` get_track_volume(track_index) set_track_volume(track_index, 0.85) ``` 4. **Track muted** - Unmute the track: ``` set_track_mute(track_index, false) ``` #### Synthesizers vs Samplers Remember the difference: | Type | Examples | Works Immediately? | | -------- | ---------------------------------- | ------------------ | | Synths | Drift, Analog, Wavetable, Operator | Yes | | Samplers | Simpler, Sampler, Drum Rack | No (need samples) | **Always prefer synthesizers** for programmatic track creation. ### Claude Configuration #### Server Not Appearing in Claude **Claude Desktop**: 1. Check config file location: * macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` * Windows: `%APPDATA%\Claude\claude_desktop_config.json` 2. Verify JSON syntax is valid 3. Restart Claude Desktop after config changes **Claude Code**: ```bash # List configured servers claude mcp list # Re-add if missing claude mcp add ableton -- uvx remix-mcp ``` #### Tools Not Available If Claude says it can't find Ableton tools: 1. Restart Claude completely 2. Check the server is properly configured 3. Verify remix-mcp is in your PATH or using full path ### Still Having Issues? 1. **Check remix-mcp status**: ```bash remix-mcp status ``` 2. **Enable logging** (for debugging): ```bash RUST_LOG=debug remix-mcp serve ``` 3. **Report an issue**: [GitHub Issues](https://github.com/christopherwxyz/remix-mcp/issues) ## Browser Tools Load instruments, effects, samples, and presets from Ableton's browser. ### Loading Instruments #### `load_default_instrument` Load the default instrument (Drift synth). :::tip Always use this for MIDI tracks that need to produce sound immediately. Drift is a synthesizer that works without loading samples. ::: #### `load_instrument` Load an instrument by name. | Parameter | Type | Description | | --------- | ------ | --------------- | | `name` | string | Instrument name | **Examples**: ``` load_instrument("Analog") load_instrument("Wavetable") load_instrument("Operator") load_instrument("Collision") ``` #### `load_drum_kit` Load a drum kit. | Parameter | Type | Description | | --------- | ------- | ------------------- | | `name` | string? | Kit name (optional) | ### Loading Effects #### `load_audio_effect` Load an audio effect. | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Effect name | **Examples**: ``` load_audio_effect("Reverb") load_audio_effect("Delay") load_audio_effect("Compressor") load_audio_effect("EQ Eight") load_audio_effect("Auto Filter") ``` #### `load_midi_effect` Load a MIDI effect. | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Effect name | **Examples**: ``` load_midi_effect("Arpeggiator") load_midi_effect("Chord") load_midi_effect("Scale") load_midi_effect("Random") ``` #### `load_default_audio_effect` Load the default audio effect (Reverb). #### `load_default_midi_effect` Load the default MIDI effect (Arpeggiator). #### `list_audio_effects` List all available audio effects. #### `list_midi_effects` List all available MIDI effects. ### Browsing #### `search_browser` Search the browser for items. | Parameter | Type | Description | | --------- | ------ | ------------ | | `query` | string | Search query | #### `browse` Browse a category. | Parameter | Type | Description | | ---------- | ------ | ------------- | | `category` | string | Category name | Categories: `Sounds`, `Drums`, `Instruments`, `Audio Effects`, `MIDI Effects`, `Max for Live`, `Plug-ins`, `Clips`, `Samples` #### `browse_path` Browse a specific path within a category. | Parameter | Type | Description | | ---------- | ------ | -------------------- | | `category` | string | Category | | `path` | string | Path within category | ### Samples & Clips #### `load_sample` Load a sample into Simpler. | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Sample name | #### `load_clip` Load an audio/MIDI clip. | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Clip name | #### `list_samples` List available samples. | Parameter | Type | Description | | ---------- | ------- | ------------------ | | `category` | string? | Filter by category | #### `list_clips` List available clips. | Parameter | Type | Description | | ---------- | ------- | ------------------ | | `category` | string? | Filter by category | ### Plugins #### `load_plugin` Load a VST/AU plugin. | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Plugin name | #### `list_plugins` List available plugins. #### `load_max_device` Load a Max for Live device. | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Device name | #### `list_max_devices` List available Max for Live devices. ### User Library #### `list_user_presets` List user presets. | Parameter | Type | Description | | ---------- | ------- | ------------------ | | `category` | string? | Filter by category | #### `load_user_preset` Load a user preset. | Parameter | Type | Description | | --------- | ------ | ----------- | | `path` | string | Preset path | ### Hotswap & Preview #### `hotswap_start` Enter hotswap mode for a device. | Parameter | Type | Description | | -------------- | ------- | ------------ | | `track_index` | integer | Track index | | `device_index` | integer | Device index | #### `hotswap_load` Load an item via hotswap. | Parameter | Type | Description | | --------- | ------ | ------------ | | `name` | string | Item to load | #### `preview_sample` Preview a sample (plays in browser). | Parameter | Type | Description | | --------- | ------ | ----------- | | `name` | string | Sample name | #### `stop_preview` Stop sample preview. ### Common Workflows #### Create a Complete Synth Track ``` 1. create_midi_track() 2. load_default_instrument() // Drift 3. load_audio_effect("Reverb") 4. load_audio_effect("Delay") 5. load_midi_effect("Arpeggiator") ``` #### Find and Load a Bass Sound ``` 1. search_browser("bass synth") 2. load_instrument("Bass") // Or specific result ``` ## Clip Tools Create, trigger, and edit clips and MIDI notes. ### Firing Clips #### `fire_clip` Start playing a clip. | Parameter | Type | Description | | ------------- | ------- | ------------------------- | | `track_index` | integer | Track containing the clip | | `clip_index` | integer | Clip slot index | #### `stop_clip` Stop a playing clip. | Parameter | Type | Description | | ------------- | ------- | --------------- | | `track_index` | integer | Track index | | `clip_index` | integer | Clip slot index | #### `fire_clip_slot` Fire a clip slot (works even if empty). ### Creating Clips #### `create_clip` Create an empty MIDI clip. | Parameter | Type | Description | | ------------- | ------- | ------------------------------ | | `track_index` | integer | Track index | | `clip_index` | integer | Clip slot index | | `length` | float | Length in beats (default: 4.0) | **Example**: ``` create_clip(track_index: 0, clip_index: 0, length: 8.0) ``` #### `duplicate_clip` Duplicate a clip to another slot. | Parameter | Type | Description | | ------------------- | ------- | ---------------- | | `track_index` | integer | Track index | | `clip_index` | integer | Source clip | | `target_clip_index` | integer | Destination slot | #### `delete_clip` Delete a clip. | Parameter | Type | Description | | ------------- | ------- | -------------- | | `track_index` | integer | Track index | | `clip_index` | integer | Clip to delete | ### Clip Info #### `list_clips` Get all clips on a track. | Parameter | Type | Description | | ------------- | ------- | ----------- | | `track_index` | integer | Track index | #### `get_clip_name` / `set_clip_name` Get or set clip name. #### `get_clip_length` Get clip length in beats. #### `get_clip_color` / `set_clip_color` Get or set clip color. ### MIDI Notes #### `add_midi_notes` Add MIDI notes to a clip. | Parameter | Type | Description | | ------------- | ------- | --------------------- | | `track_index` | integer | Track index | | `clip_index` | integer | Clip index | | `notes` | array | Array of note objects | Each note object: ```json { "pitch": 60, // MIDI note (0-127, 60 = C4) "start": 0.0, // Start time in beats "duration": 1.0, // Duration in beats "velocity": 100, // Velocity (1-127) "mute": false // Optional } ``` **Example**: Add a C major chord ``` add_midi_notes( track_index: 0, clip_index: 0, notes: [ { pitch: 60, start: 0, duration: 4, velocity: 100 }, // C { pitch: 64, start: 0, duration: 4, velocity: 100 }, // E { pitch: 67, start: 0, duration: 4, velocity: 100 } // G ] ) ``` #### `get_midi_notes` Get all MIDI notes in a clip. | Parameter | Type | Description | | ------------- | ------- | ----------- | | `track_index` | integer | Track index | | `clip_index` | integer | Clip index | #### `remove_midi_notes` Remove notes from a clip. | Parameter | Type | Description | | ------------- | -------- | ---------------------------- | | `track_index` | integer | Track index | | `clip_index` | integer | Clip index | | `start` | float? | Start beat (optional filter) | | `end` | float? | End beat (optional filter) | | `pitch_min` | integer? | Min pitch (optional filter) | | `pitch_max` | integer? | Max pitch (optional filter) | #### `replace_midi_notes` Replace all notes in a clip. ### Loop Settings #### `get_clip_looping` / `set_clip_looping` Get or set whether clip loops. #### `get_clip_loop_start` / `set_clip_loop_start` Get or set loop start point. #### `get_clip_loop_end` / `set_clip_loop_end` Get or set loop end point. ### Common Workflows #### Create a Simple Melody ``` 1. create_clip(0, 0, length: 4) 2. add_midi_notes(0, 0, [ { pitch: 60, start: 0, duration: 0.5, velocity: 100 }, { pitch: 62, start: 0.5, duration: 0.5, velocity: 100 }, { pitch: 64, start: 1, duration: 0.5, velocity: 100 }, { pitch: 65, start: 1.5, duration: 0.5, velocity: 100 }, { pitch: 67, start: 2, duration: 2, velocity: 100 } ]) 3. fire_clip(0, 0) ``` #### MIDI Note Reference | Note | MIDI | Note | MIDI | | ---- | ---- | ---- | ---- | | C3 | 48 | C4 | 60 | | D3 | 50 | D4 | 62 | | E3 | 52 | E4 | 64 | | F3 | 53 | F4 | 65 | | G3 | 55 | G4 | 67 | | A3 | 57 | A4 | 69 | | B3 | 59 | B4 | 71 | ## Cue Point Tools Navigate using cue points (markers) in the arrangement. ### Listing Cue Points #### `list_cue_points` Get all cue points in the song. **Returns**: Array of cue points with names and positions. ### Navigation #### `jump_to_cue_point` Jump playback to a cue point. | Parameter | Type | Description | | ----------- | ------- | --------------- | | `cue_index` | integer | Cue point index | #### `jump_to_next_cue_point` Jump to the next cue point from current position. #### `jump_to_previous_cue_point` Jump to the previous cue point from current position. ### Creating Cue Points #### `create_cue_point` Create a cue point at the current position. | Parameter | Type | Description | | --------- | ------- | ------------- | | `name` | string? | Optional name | #### `delete_cue_point` Delete a cue point. | Parameter | Type | Description | | ----------- | ------- | ------------------- | | `cue_index` | integer | Cue point to delete | ### Common Workflows #### Mark Song Sections ``` 1. jump_to_beat(0) 2. create_cue_point("Intro") 3. jump_to_beat(32) 4. create_cue_point("Verse 1") 5. jump_to_beat(64) 6. create_cue_point("Chorus") ``` #### Navigate During Playback ``` 1. play() 2. // Listen to intro... 3. jump_to_next_cue_point() // Skip to verse 4. // Listen to verse... 5. jump_to_next_cue_point() // Skip to chorus ``` #### Quick Section Review ``` 1. list_cue_points() // See all markers 2. jump_to_cue_point(2) // Jump to specific section 3. play() // Listen from there ``` ## Device Tools Control instruments and effects on tracks. ### Listing Devices #### `list_devices` Get all devices on a track. | Parameter | Type | Description | | ------------- | ------- | ----------- | | `track_index` | integer | Track index | **Returns**: Array of device info including names and parameter counts. #### `get_device_name` Get a device's name. | Parameter | Type | Description | | -------------- | ------- | ------------------------ | | `track_index` | integer | Track index | | `device_index` | integer | Device position in chain | ### Device Parameters #### `get_device_parameter` Get a parameter value. | Parameter | Type | Description | | ----------------- | ------- | --------------- | | `track_index` | integer | Track index | | `device_index` | integer | Device index | | `parameter_index` | integer | Parameter index | #### `set_device_parameter` Set a parameter value. | Parameter | Type | Description | | ----------------- | ------- | -------------------------------- | | `track_index` | integer | Track index | | `device_index` | integer | Device index | | `parameter_index` | integer | Parameter index | | `value` | float | New value (0.0 - 1.0 normalized) | #### `list_device_parameters` Get all parameters for a device. | Parameter | Type | Description | | -------------- | ------- | ------------ | | `track_index` | integer | Track index | | `device_index` | integer | Device index | **Returns**: Array with parameter names, values, min, max. ### Device State #### `get_device_enabled` / `set_device_enabled` Get or set whether device is enabled (bypassed). | Parameter | Type | Description | | -------------- | ------- | ---------------------- | | `track_index` | integer | Track index | | `device_index` | integer | Device index | | `enabled` | boolean | Enable state (for set) | ### Common Workflows #### Adjust Reverb Decay ``` 1. list_devices(0) // Find device indices 2. list_device_parameters(0, 1) // List reverb params 3. set_device_parameter(0, 1, 2, 0.7) // Adjust decay ``` #### Bypass an Effect ``` set_device_enabled(0, 1, false) // Bypass device 1 on track 0 ``` #### Automate Parameters While automation isn't directly supported, you can create interesting effects by rapidly changing parameters: ``` // Sweep a filter cutoff for value in [0.1, 0.3, 0.5, 0.7, 0.9]: set_device_parameter(0, 1, 3, value) ``` ### Device Chain Order Devices are indexed by their position in the chain: ``` Track 0: [0] Drift (Instrument) [1] Auto Filter (Effect) [2] Reverb (Effect) [3] Limiter (Effect) ``` The instrument is typically at index 0, followed by effects. ## Tools Reference remix-mcp provides **266 tools** for controlling Ableton Live. This section documents all available tools organized by category. ### Overview | Category | Count | Description | | ------------------------------- | ----- | ------------------------------------------- | | [Transport](/tools/transport) | 10 | Playback control: play, stop, record, tempo | | [Tracks](/tools/tracks) | 59 | Create, modify, route audio/MIDI tracks | | [Clips](/tools/clips) | 65 | Create, fire, edit clips and MIDI notes | | [Scenes](/tools/scenes) | 19 | Scene management and triggering | | [Devices](/tools/devices) | 10 | Control instruments and effects | | [Song](/tools/song) | 56 | Global settings, undo/redo, loops | | [Browser](/tools/browser) | 29 | Load instruments, effects, samples | | [View](/tools/view) | 8 | Selection and navigation | | [Cue Points](/tools/cue-points) | 5 | Marker navigation | ### How Tools Work Tools are invoked by Claude through the MCP protocol. Each tool: 1. Receives parameters from Claude 2. Sends OSC messages to AbletonOSC 3. Returns results or confirmation #### Example Flow When you ask Claude to "set the tempo to 128 BPM": ``` Claude: "I'll set the tempo to 128 BPM" | v [MCP: call set_tempo(tempo: 128)] | v [OSC: /live/song/set/tempo 128.0] | v [Ableton: tempo changes to 128] | v Claude: "Done! The tempo is now 128 BPM" ``` ### Tool Naming Conventions Tools follow consistent naming patterns: | Pattern | Purpose | Example | | ---------- | ------------------ | -------------------------------------- | | `get_*` | Read current value | `get_tempo`, `get_track_volume` | | `set_*` | Change a value | `set_tempo`, `set_track_volume` | | `create_*` | Create new item | `create_midi_track`, `create_clip` | | `delete_*` | Remove item | `delete_track`, `delete_clip` | | `fire_*` | Trigger playback | `fire_clip`, `fire_scene` | | `list_*` | Get all items | `list_tracks`, `list_devices` | | `load_*` | Load from browser | `load_instrument`, `load_audio_effect` | ### Common Parameters Many tools share common parameter types: | Parameter | Type | Description | | -------------- | ------- | --------------------------------- | | `track_index` | integer | Track number (0-indexed) | | `clip_index` | integer | Clip slot number (0-indexed) | | `scene_index` | integer | Scene number (0-indexed) | | `device_index` | integer | Device chain position (0-indexed) | :::tip All indices are **0-based**. Track 1 in Ableton's UI is `track_index: 0`. ::: ### Error Handling Tools return errors for invalid operations: * **InvalidParameter**: Bad input (e.g., negative index) * **InvalidResponse**: Unexpected response from Ableton * **Timeout**: No response within 5 seconds * **Network**: Connection issues ## Scene Tools Manage and trigger scenes in Session View. ### Firing Scenes #### `fire_scene` Launch all clips in a scene. | Parameter | Type | Description | | ------------- | ------- | ------------- | | `scene_index` | integer | Scene to fire | #### `stop_all_clips` Stop all playing clips. ### Scene Management #### `list_scenes` Get information about all scenes. **Returns**: Array of scene info objects. #### `create_scene` Create a new empty scene. | Parameter | Type | Description | | --------- | -------- | ------------------- | | `index` | integer? | Position (-1 = end) | #### `delete_scene` Delete a scene. | Parameter | Type | Description | | ------------- | ------- | --------------- | | `scene_index` | integer | Scene to delete | #### `duplicate_scene` Duplicate a scene with all its clips. | Parameter | Type | Description | | ------------- | ------- | ------------------ | | `scene_index` | integer | Scene to duplicate | ### Scene Properties #### `get_scene_name` / `set_scene_name` Get or set scene name. | Parameter | Type | Description | | ------------- | ------- | ------------------ | | `scene_index` | integer | Scene index | | `name` | string | New name (for set) | #### `get_scene_tempo` / `set_scene_tempo` Get or set scene tempo (if different from master). #### `get_scene_color` / `set_scene_color` Get or set scene color. ### Common Workflows #### Set Up Song Sections ``` 1. create_scene(0) // Intro 2. set_scene_name(0, "Intro") 3. create_scene(1) // Verse 4. set_scene_name(1, "Verse") 5. create_scene(2) // Chorus 6. set_scene_name(2, "Chorus") ``` #### Live Performance ``` 1. fire_scene(0) // Start with intro 2. // Wait... 3. fire_scene(1) // Transition to verse 4. // Wait... 5. fire_scene(2) // Hit the chorus ``` #### Scene Color Coding Use colors to organize your arrangement: * **Green**: Intros/Outros * **Blue**: Verses * **Red**: Choruses * **Yellow**: Bridges ``` set_scene_color(0, 0x00FF00) // Green intro set_scene_color(1, 0x0000FF) // Blue verse set_scene_color(2, 0xFF0000) // Red chorus ``` ## Song Tools Global song settings, undo/redo, loop controls, and more. ### Undo/Redo #### `undo` Undo the last action. #### `redo` Redo the last undone action. #### `can_undo` Check if undo is available. **Returns**: `boolean` #### `can_redo` Check if redo is available. **Returns**: `boolean` ### Loop Settings #### `get_loop` / `set_loop` Get or set loop enabled state. #### `get_loop_start` / `set_loop_start` Get or set loop start position (in beats). #### `get_loop_length` / `set_loop_length` Get or set loop length (in beats). **Example**: Set up an 8-bar loop starting at bar 5 ``` set_loop_start(16.0) // Beat 16 = bar 5 set_loop_length(32.0) // 32 beats = 8 bars set_loop(true) // Enable loop ``` ### Time Signature #### `get_signature_numerator` / `set_signature_numerator` Get or set time signature numerator (beats per bar). #### `get_signature_denominator` / `set_signature_denominator` Get or set time signature denominator (beat unit). **Example**: Set to 6/8 time ``` set_signature_numerator(6) set_signature_denominator(8) ``` ### Quantization #### `get_quantization` Get global quantization value. **Returns**: Quantization setting (e.g., "1 Bar", "1/4", "1/8") #### `set_quantization` Set global quantization. | Parameter | Type | Description | | --------- | ------- | ------------------ | | `value` | integer | Quantization index | Common values: * 0 = None * 1 = 8 Bars * 2 = 4 Bars * 3 = 2 Bars * 4 = 1 Bar * 5 = 1/2 * 6 = 1/4 * 7 = 1/8 * 8 = 1/16 ### Groove #### `get_groove_amount` / `set_groove_amount` Get or set global groove amount (0.0 - 1.0). ### Metronome #### `get_metronome` / `set_metronome` Get or set metronome on/off. ### Song Position #### `get_current_beat` Get current playback position in beats. #### `jump_to_beat` Jump to a specific beat position. | Parameter | Type | Description | | --------- | ----- | ------------- | | `beat` | float | Beat position | #### `jump_to_bar` Jump to a specific bar. | Parameter | Type | Description | | --------- | ------- | ---------------------- | | `bar` | integer | Bar number (1-indexed) | ### Master Track #### `get_master_volume` / `set_master_volume` Get or set master track volume. #### `get_master_pan` / `set_master_pan` Get or set master track pan. ### Song Info #### `get_song_name` Get the song/project name. #### `get_song_length` Get total song length in beats. ### Common Workflows #### Set Up a Practice Loop ``` 1. set_tempo(100) // Slower tempo 2. set_loop_start(0) // From beginning 3. set_loop_length(16) // 4 bars 4. set_loop(true) // Enable 5. set_metronome(true) // Turn on click 6. play() // Start practicing ``` #### Quick Arrangement Check ``` 1. set_loop(false) // Disable loop 2. jump_to_beat(0) // Go to start 3. play() // Listen through ``` ## Track Tools Create and control audio and MIDI tracks. ### Creating Tracks #### `create_audio_track` Create a new audio track. | Parameter | Type | Description | | --------- | -------- | ------------------- | | `index` | integer? | Position (-1 = end) | **Returns**: Track index of the new track. #### `create_midi_track` Create a new MIDI track. | Parameter | Type | Description | | --------- | -------- | ------------------- | | `index` | integer? | Position (-1 = end) | **Returns**: Track index of the new track. #### `create_return_track` Create a new return track. #### `delete_track` Delete a track. | Parameter | Type | Description | | ------------- | ------- | --------------- | | `track_index` | integer | Track to delete | #### `duplicate_track` Duplicate a track with all its clips and devices. | Parameter | Type | Description | | ------------- | ------- | ------------------ | | `track_index` | integer | Track to duplicate | ### Track Info #### `list_tracks` Get information about all tracks. **Returns**: Array of track info objects. #### `get_track_name` Get a track's name. | Parameter | Type | Description | | ------------- | ------- | ----------- | | `track_index` | integer | Track index | #### `set_track_name` Set a track's name. | Parameter | Type | Description | | ------------- | ------- | ----------- | | `track_index` | integer | Track index | | `name` | string | New name | ### Volume & Pan #### `get_track_volume` Get track volume (0.0 - 1.0). #### `set_track_volume` Set track volume. | Parameter | Type | Description | | ------------- | ------- | ------------------ | | `track_index` | integer | Track index | | `volume` | float | Volume (0.0 - 1.0) | #### `get_track_pan` Get track pan (-1.0 left to 1.0 right). #### `set_track_pan` Set track pan. | Parameter | Type | Description | | ------------- | ------- | ----------------- | | `track_index` | integer | Track index | | `pan` | float | Pan (-1.0 to 1.0) | ### Mute, Solo, Arm #### `get_track_mute` / `set_track_mute` Get or set track mute state. #### `get_track_solo` / `set_track_solo` Get or set track solo state. #### `get_track_arm` / `set_track_arm` Get or set track arm state (for recording). #### `arm_track` Convenience method to arm a track. | Parameter | Type | Description | | ------------- | ------- | ----------- | | `track_index` | integer | Track index | ### Sends #### `get_track_send` Get send level to a return track. | Parameter | Type | Description | | ------------- | ------- | ------------------ | | `track_index` | integer | Source track | | `send_index` | integer | Return track index | #### `set_track_send` Set send level. | Parameter | Type | Description | | ------------- | ------- | ---------------------- | | `track_index` | integer | Source track | | `send_index` | integer | Return track index | | `value` | float | Send level (0.0 - 1.0) | ### Routing #### `get_track_input_routing` / `set_track_input_routing` Control where track receives input from. #### `get_track_output_routing` / `set_track_output_routing` Control where track sends output to. ### Common Workflows #### Create a Synth Track ``` 1. create_midi_track() // Creates at index N 2. load_default_instrument() // Loads Drift synth 3. set_track_name(N, "Lead") // Name it ``` #### Set Up Sends ``` 1. create_return_track() // Create return 2. load_audio_effect("Reverb") // Add reverb to return 3. set_track_send(0, 0, 0.5) // Send from track 0 ``` ## Transport Tools Control playback, recording, and tempo. ### Playback #### `play` Start playback from the current position. #### `stop` Stop playback. #### `continue_playing` Continue playback from where it stopped. #### `stop_playing` Stop playback and return to start. ### Recording #### `start_recording` Start recording (arms selected tracks if needed). #### `stop_recording` Stop recording. #### `is_playing` Returns whether playback is active. **Returns**: `boolean` #### `is_recording` Returns whether recording is active. **Returns**: `boolean` ### Tempo #### `get_tempo` Get the current tempo in BPM. **Returns**: `float` (e.g., `120.0`) #### `set_tempo` Set the tempo. | Parameter | Type | Description | | --------- | ----- | --------------------------- | | `tempo` | float | Tempo in BPM (20.0 - 999.0) | **Example**: ``` set_tempo(tempo: 128.0) ``` ### Common Workflows #### Start a Session ``` 1. set_tempo(120) // Set your tempo 2. play() // Start playback ``` #### Record a Performance ``` 1. arm_track(0) // Arm track for recording 2. start_recording() // Begin recording 3. // ... perform ... 4. stop_recording() // Stop when done ``` ## View Tools Control selection and navigation in Ableton's UI. ### Track Selection #### `select_track` Select a track. | Parameter | Type | Description | | ------------- | ------- | --------------- | | `track_index` | integer | Track to select | #### `get_selected_track` Get the currently selected track index. **Returns**: `integer` ### Clip Selection #### `select_clip` Select a clip slot. | Parameter | Type | Description | | ------------- | ------- | --------------- | | `track_index` | integer | Track index | | `clip_index` | integer | Clip slot index | #### `get_selected_clip` Get the currently selected clip. **Returns**: `{ track_index, clip_index }` ### Scene Selection #### `select_scene` Select a scene. | Parameter | Type | Description | | ------------- | ------- | --------------- | | `scene_index` | integer | Scene to select | #### `get_selected_scene` Get the currently selected scene index. **Returns**: `integer` ### Device Selection #### `select_device` Select a device on a track. | Parameter | Type | Description | | -------------- | ------- | ---------------- | | `track_index` | integer | Track index | | `device_index` | integer | Device to select | ### Common Workflows #### Navigate to a Specific Clip ``` 1. select_track(2) // Go to track 3 2. select_clip(2, 4) // Select clip at scene 5 ``` #### Work with Selected Items Many operations work with the "selected" item: ``` 1. select_track(0) 2. load_default_instrument() // Loads on selected track ``` #### Programmatic Navigation Build a workflow that navigates through your arrangement: ``` for scene in range(4): select_scene(scene) fire_scene(scene) // Wait for scene to play... ```