flai-mcp
by kaupau
README.md
# flai-mcp
MCP server that connects Claude to FL Studio for AI-assisted music production.
> **Status:** Alpha — functional core, actively developed. Contributions welcome.
```
Claude Code / Claude Desktop / Cursor
│ MCP (stdio)
▼
flai-mcp server (Python)
│
Virtual MIDI (SysEx)
(IAC Driver / loopMIDI)
│
device_flai.py
(MIDI controller script
running inside FL Studio)
```
## What it can do
| Category | Capabilities |
|----------|-------------|
| **Transport** | Play, stop, record, get/set tempo, seek to bar/beat |
| **Mixer** | Get/set volume, pan, mute, solo, name, color for any track |
| **Channel Rack** | Get/set volume, pan, pitch, name, mute, mixer routing |
| **Patterns** | List, rename, recolor, clone, navigate between patterns |
| **Notes** | Write notes into patterns with pitch, velocity, timing via step sequencer API |
| **Plugins** | List parameters, get/set values, cycle presets |
| **Arrangement** | Add/list timeline markers, get playhead position |
| **Playlist** | Name and color playlist tracks |
### Example prompts
> "Write a four-on-the-floor kick pattern in pattern 1"
> "Add a rolling bassline in A minor to pattern 5 on the FLEX Bass channel"
> "Turn down the kick on mixer track 2 by 3dB and hard-pan the hi-hats"
> "Set the cutoff on channel 4 to 60% and resonance to 25%"
> "Add arrangement markers for Intro, Buildup, Drop, Breakdown, and Outro"
## Known limitations
- **Playlist clip placement** — FL Studio's scripting API does not expose any function to place pattern clips on the arrangement timeline. This is an API gap from Image-Line, not a flai-mcp limitation. Patterns must be arranged manually. ([API audit](https://il-group.github.io/FL-Studio-API-Stubs/midi_controller_scripting/playlist/))
- **Note writing uses step sequencer** — Notes are written via `setGridBit` + `setStepParameterByIndex`. This works for drums and melodic patterns with 1/16th note quantization. Sub-step timing is supported via the shift parameter, but it's not as flexible as the Piano Roll.
- **Piano Roll scripts can't do file I/O on macOS** — FL Studio's embedded Python `open()` is broken on macOS, so the file-based piano roll bridge doesn't work. The step sequencer approach is the current workaround.
- **Tempo setting** — Requires FL Studio 21+. Use the FL Studio UI for older versions.
## Setup
### 1. Virtual MIDI ports
**macOS (IAC Driver — built-in, free)**
1. Open **Audio MIDI Setup** (Spotlight → "Audio MIDI Setup")
2. Window → Show MIDI Studio
3. Double-click **IAC Driver** → check **Device is online**
4. Add two ports: `FLAI In` and `FLAI Out`
**Windows (loopMIDI — free)**
1. Install [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)
2. Create two ports: `FLAI In` and `FLAI Out`
### 2. Install flai-mcp
```bash
# Clone
git clone https://github.com/kaupau/flai-mcp.git
cd flai-mcp
# Create venv and install (requires Python 3.11+)
uv venv --python 3.11 .venv
uv pip install -e .
# Or with pip
python -m venv .venv
source .venv/bin/activate
pip install -e .
```
### 3. Install FL Studio bridge script
```bash
python scripts/install_fl_bridge.py
```
Or manually copy `fl_bridge/device_flai.py` to:
- **macOS:** `~/Documents/Image-Line/FL Studio/Settings/Hardware/FLAI/device_flai.py`
- **Windows:** `%USERPROFILE%\Documents\Image-Line\FL Studio\Settings\Hardware\FLAI\device_flai.py`
### 4. Configure FL Studio
1. Open FL Studio
2. **Options → MIDI Settings**
3. **Input section:**
- Select `IAC Driver FLAI In` (or `FLAI In` on Windows)
- Set **Controller type** to **FLAI**
- Set **Port** to `1`
- Click **Enable**
4. **Output section:**
- Select `IAC Driver FLAI Out` (or `FLAI Out` on Windows)
- Set **Port** to `1`
- Click **Enable**
Verify it works: open **View → Script output** — you should see:
```
[FLAI] MCP Bridge initialized. Ready.
[FLAI] Input port: IAC Driver FLAI In
```
### 5. Configure your AI client
**Claude Code** — add to `~/.claude/settings.json`:
```json
{
"mcpServers": {
"flai": {
"command": "/path/to/flai-mcp/.venv/bin/flai-mcp",
"args": ["--midi-in", "IAC Driver FLAI In", "--midi-out", "IAC Driver FLAI Out"]
}
}
}
```
**Cursor** — add to `~/.cursor/mcp.json` (same format).
**Claude Desktop** — add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"flai": {
"command": "/path/to/flai-mcp/.venv/bin/flai-mcp",
"args": ["--midi-in", "IAC Driver FLAI In", "--midi-out", "IAC Driver FLAI Out"]
}
}
}
```
### 6. Verify
```bash
# List available MIDI ports
flai-mcp --list-ports
# Run with debug logging
flai-mcp --log-level DEBUG
```
## Architecture
```
src/flai_mcp/
├── server.py — MCP server assembly
├── __main__.py — CLI entry point (flai-mcp)
├── bridges/
│ └── midi_bridge.py — async SysEx ↔ asyncio bridge via mido
├── protocol/
│ ├── commands.py — command/status enums
│ └── encoding.py — SysEx ↔ JSON serialization
└── tools/
├── transport.py — play/stop/tempo/position
├── mixer.py — mixer track controls
├── channels.py — channel rack controls
├── patterns.py — pattern management
├── piano_roll.py — note writing (step sequencer API)
├── plugins.py — plugin parameters & presets
└── arrangement.py — timeline markers
fl_bridge/
└── device_flai.py — FL Studio MIDI Controller Script
```
### Protocol
Commands are SysEx messages with JSON payloads:
```
Request: [0xF0, 0x7D, CMD_ID, REQ_ID, <ascii-json>, 0xF7]
Response: [0xF0, 0x7D, 0x70, REQ_ID, STATUS, <ascii-json>, 0xF7]
```
- `0x7D` — SysEx manufacturer ID reserved for non-commercial/educational use
- JSON uses `ensure_ascii=True` so all payload bytes are 0x00–0x7F (SysEx-safe)
- Responses are matched by `REQ_ID` (0–127, rotating counter)
### How note writing works
FL Studio's MIDI Controller Scripting API doesn't expose piano roll note editing. The `flpianoroll` module only works in Piano Roll Scripts, which run in a separate Python context with broken file I/O on macOS.
flai-mcp writes notes via the **step sequencer API**:
- `channels.setGridBit(channel, step, on/off)` — enable/disable steps
- `channels.setStepParameterByIndex(channel, pattern, step, param, value)` — set pitch, velocity, pan, timing per step
This gives per-note control over pitch (param 0), velocity (param 1), pan (param 4), and micro-timing (param 7).
## Development
```bash
git clone https://github.com/kaupau/flai-mcp.git
cd flai-mcp
uv venv --python 3.11 .venv
uv pip install -e ".[dev]"
# Run protocol tests (no FL Studio needed)
pytest
# Check ports
flai-mcp --list-ports
```
### Adding new tools
1. Add command ID to `src/flai_mcp/protocol/commands.py`
2. Add handler in `fl_bridge/device_flai.py` → `_HANDLERS` dispatch table
3. Add MCP tool in `src/flai_mcp/tools/*.py`
4. Reinstall the FL Studio script: `python scripts/install_fl_bridge.py`
## Contributing
Contributions welcome! Some areas that need work:
- [ ] **Piano Roll note writing** — find a way to use `flpianoroll.score.addNote()` programmatically (the subprocess IPC approach from [music-copilot](https://github.com/TommyX12/music-copilot) is promising)
- [ ] **Playlist clip placement** — lobby Image-Line for `playlist.addClip()` API, or explore `.flp` file manipulation via [PyFLP](https://github.com/demberto/PyFLP)
- [ ] **Windows testing** — loopMIDI setup, path handling
- [ ] **Automation clips** — create and manipulate automation
- [ ] **Better tempo control** — `mixer.setCurrentTempo()` doesn't exist in all versions
- [ ] **Audio rendering** — export/bounce support if API allows
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues