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)
- 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)
- Open Audio MIDI Setup (Spotlight → "Audio MIDI Setup")
- Window → Show MIDI Studio
- Double-click IAC Driver → check Device is online
- Add two ports:
FLAI InandFLAI Out
Windows (loopMIDI — free)
- Install loopMIDI
- Create two ports:
FLAI InandFLAI Out
2. Install flai-mcp
# 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
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
- Open FL Studio
- Options → MIDI Settings
- Input section:
- Select
IAC Driver FLAI In(orFLAI Inon Windows) - Set Controller type to FLAI
- Set Port to
1 - Click Enable
- Select
- Output section:
- Select
IAC Driver FLAI Out(orFLAI Outon Windows) - Set Port to
1 - Click Enable
- Select
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:
{
"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:
{
"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
# 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=Trueso 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 stepschannels.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
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
- Add command ID to
src/flai_mcp/protocol/commands.py - Add handler in
fl_bridge/device_flai.py→_HANDLERSdispatch table - Add MCP tool in
src/flai_mcp/tools/*.py - 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 is promising) - Playlist clip placement — lobby Image-Line for
playlist.addClip()API, or explore.flpfile manipulation via 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