flstudio-mcp
This MCP server lets Claude inspect, control, compose, and mix in FL Studio through reversible, safety-checked tools.
Connection/transport: ping FL, read tempo/project/play state/song position, set tempo, play/stop/toggle play, toggle record, set playhead.
Mixer/channel control: read mixer/channel state and routing; set volume, pan, mute, solo, rename; group tracks into buses, bulk solo/mute, clear mutes/solos, color tracks/channels.
Safety: take snapshots, enable dry-run mode, roll back last change.
Mix diagnosis: scan the mix, run full-song peak watch, propose gain staging, compare to reference, apply approved trim fixes.
Plugin control: list loaded plugins and parameters, set plugin parameters, apply EQ/reverb/delay/compression intents, list installed plugins and presets, suggest presets and processing chains.
Composition/MIDI: write piano-roll notes, quantize notes, create/select/clone patterns, add markers, write raga melodies/chords, export multi-track MIDI.
Audio analysis: estimate tempo/key, extract melody from audio, reference-match analysis.
Utilities: measure track level, detect cleanup candidates.
flstudio-mcp
Control FL Studio with Claude: AI mixing, composition, and mix diagnosis through natural language.

Claude diagnosing and fixing a mix in FL Studio through natural language.
Overview
flstudio-mcp is a Model Context Protocol (MCP) server that lets Claude (Claude Code or Claude Desktop) drive FL Studio 2025 directly — the mixer, plugins, piano roll, routing, and project — from plain-language requests. Ask for a mix diagnosis, a vocal chain, a chord progression in a particular scale, or a full arrangement, and Claude carries it out through FL's scripting API and a set of calibrated, safety-checked tools.
It is genre- and producer-agnostic: nothing about it assumes a particular style of music.
Related MCP server: FL Studio MCP Server
Quickstart
For a new FL Studio setup, clone the repository so the controller and installer scripts are available:
git clone https://github.com/rosasynthesiz/flstudio-mcp.git
cd flstudio-mcpThen run the installer for your OS. It installs the server into its environment, copies the FL controller, and seeds the note bridge:
:: first: in loopMIDI, create two ports named exactly "FLStudioMCP RX" and "FLStudioMCP TX"
scripts\install_windows.bat :: controller + server (.venv) + note bridge
scripts\start_daemon.bat :: start the bridge in its own window, keep it open./scripts/install_macos.sh # macOS: controller + server + note bridge
fl-studio-mcp-daemon # start the bridge, keep it runningWire the two virtual MIDI ports in FL (loopMIDI on Windows, IAC Driver on
macOS), arm MCP_Apply once in the piano roll, then ask Claude in plain
language:
"Scan my mix and tell me what's wrong." — "Set up a vocal chain from my plugins." — "Export this arrangement to MIDI."
Full setup is below.
For an environment whose FL controller and MIDI bridge are already configured, the server package is also available from PyPI:
python -m pip install fl-studio-mcpThe PyPI package does not replace the controller/port setup above. The current
main branch may contain changes that have not yet been released to PyPI.
Capabilities
Mixing & diagnosis
Mix Doctor — scans the whole mix and reports concrete problems (clipping, low headroom, level imbalance, missing high-pass, ungrouped related tracks, overlapping EQ boosts), each with the exact evidence and a proposed fix. Fixes are applied one at a time, only on approval, through a snapshot → write → readback → rollback safety layer. Master clipping is resolved by trimming the contributing source tracks rather than pulling the master.
Full-song peak watch — holds a running peak per track across playback, so level decisions are based on the loudest moment of the actual song, not a single instant.
Calibrated processing intents — musical EQ, compression, reverb, and delay moves mapped to real plugin parameters (native and third-party), each applied as one reversible change.
Level-aware compression — sets thresholds relative to a track's measured level during playback.
Gain staging — proposes per-track trims toward a healthy level with proper master headroom.
Reference match — compares your mix's level and tonal balance against a reference track.
Bulk track control — solo or mute a whole group (drums, vocals, …) in one step, with a one-call reset.
Track & channel coloring — color a track, a channel, or a whole group (drums, vocals, …) by color name or hex, reversible like every other change.
Plugin & preset control
Read and set plugin parameters by name, on native and third-party plugins (the parameter list is resolved live).
Verified writes — every parameter write is re-read on a fresh tick and retried (0.4 s apart) if FL did not take it; the answer carries
verified/attemptsand ahint, so a swallowed write is reported instead of echoed back as if it worked.Batch parameter changes —
fl_plugin_set_paramssets several knobs of one plugin in a single paced burst and one undo step;fl_rollback_last_changeputs them all back together.Chain suggestions and preset recommendations drawn from your actual installed library — read directly from FL's plugin database and preset folders on disk, so recommendations are limited to what you own.
Composition
Multi-track MIDI export — generate a complete arrangement as a standard MIDI file to import.
Multi-pattern arrangement — create, name, clone, and mark sections.
Drum patterns in the step sequencer: read or set a channel's steps in the current pattern, e.g.
x...x...x...x..., reversible like every other change.Note and chord writing into the piano roll, with quantize to a grid (for new notes and existing ones).
Composition in any scale or mode — Western modes, pentatonic, ragas, maqam, and beyond — through the scale composer, where Claude supplies the notes for the requested scale.
Audio analysis
Tempo and key estimation from an audio file.
Melody-to-MIDI transcription (CREPE pitch tracking, with a lighter fallback).
Chords-to-MIDI transcription of polyphonic audio (keys, piano, guitar) with Spotify's Basic Pitch, as notes for the piano roll or a
.midfile.Drums to MIDI: a drum loop or stem to kick, snare, clap, closed and open hi-hat, aligned to the beat, as a
.midor straight into the step sequencer of the channels you choose (one undo step).
The server exposes 72 tools across 14 categories, plus 6 live resources (project, mixer, transport, channels, patterns, status) that Claude can read directly.
What sets it apart
flstudio-mcp is built as a mixing and production assistant, not only a note sender. It diagnoses and repairs a whole mix, makes decisions from real measured levels rather than guesswork, and is aware of your actual plugin and preset library when it makes suggestions. Every change that touches the project is shown before it is applied, logged, and reversible.
Limitations
These are properties of FL Studio's scripting API, stated plainly:
Plugins, audio files, and rendering are UI-only. FL's API cannot load a plugin, load an audio file, or render audio. The plugin and preset tools therefore suggest — you load the chosen plugin or preset, and Claude then configures it. Audio export is done manually (File > Export); Claude can analyze the rendered file afterward.
Only some plugin parameters accept arbitrary values. Levels and gains do; stepped parameters (filter types, orders, selectors) snap to their own grid steps, so an off-grid request cannot land; some parameters (Fruity Parametric EQ 2's band widths) ignore writes entirely. The parameter tools re-read and retry, then report
verified: falsewith ahintand the value FL actually holds, instead of echoing the request as if it had landed.Note writing is armed once per session. A generated pyscript writes notes into the piano roll; FL exposes no API to run a pyscript, so you run "MCP_Apply" once from the piano roll's scripting menu at the start of a session.
Micro-tonal and gamaka-heavy music is approximated. Scales with intervals smaller than a semitone (e.g. Arabic maqam) are rounded to the nearest semitone, and traditions built on gamaka/ornamentation (e.g. Carnatic) get the scale framework — the correct swaras and intervals — not gamaka or micro-tonal rendering. That's a limit of 12-tone MIDI, not of the tools.
Requirements
Windows 10/11 (tested on Windows 11) or macOS
FL Studio 2025 or newer
Claude Code or Claude Desktop (or any MCP client)
Python 3.10+
Virtual MIDI ports:
Windows: loopMIDI (download)
macOS: the built-in IAC Driver
Optional: ffmpeg on PATH (for MP3 analysis)
Linux is not yet supported — contributions welcome.
Setup
Create two virtual MIDI ports, named exactly
FLStudioMCP RXandFLStudioMCP TX. These are the "cables" between the MCP server and FL Studio: one carries commands into FL (RX), the other carries answers back (TX). Do this before running the installer, because it checks for them.Windows (loopMIDI):
Install and open loopMIDI.
If the list already holds ports with default names (
loopMIDI Port,loopMIDI Port 1, …), select them and click − to remove them. The default names will not be detected.In the New port-name box at the bottom, type
FLStudioMCP RXand click +.Type
FLStudioMCP TXand click + again.Keep loopMIDI running (it can start with Windows from its tray icon); the ports exist only while it runs.
macOS:
Open Audio MIDI Setup.
Choose Window > Show MIDI Studio.
Double-click IAC Driver.
Enable Device is online.
Create or rename two ports exactly:
FLStudioMCP RXFLStudioMCP TX
Install the controller script and server:
Windows:
git clone https://github.com/rosasynthesiz/flstudio-mcp cd flstudio-mcp scripts\install_windows.batmacOS:
git clone https://github.com/rosasynthesiz/flstudio-mcp cd flstudio-mcp chmod +x scripts/install_macos.sh ./scripts/install_macos.shThis copies the controller script, seeds the note-bridge pyscript (
MCP_Apply), installs the server, and checks that your virtual MIDI ports exist.On Windows the server is installed into a
.venvfolder inside the repo, using Python 3.12/3.11/3.10 when available (the MIDI library has no working build for newer Pythons on Windows). The installer prints the full paths of the commands to use in the next steps. It finds your Documents folder even when it is redirected (OneDrive, non-English names). All FL Studio versions (2024, 2025, 2026, …) share one user-data folder, so one install covers them all. It also follows FL's own "User data folder" setting; if it still can't find the folder, runsetx FL_SETTINGS "<folder>\FL Studio\Settings"once and open a new terminal (the installer and the daemon both use it).Both installers ask two optional questions (re-run the installer any time to add them):
Audio analysis (about 100 MB, no AI models): tempo and key detection, drums to MIDI, light melody to MIDI, reference match.
AI audio to MIDI (about 650 MB, downloads AI models): accurate melody to MIDI with CREPE, full chords with Spotify's Basic Pitch.
To answer without the prompts, set
FLMCP_EXTRASfirst:all,none, or any ofaudio accurate chords.Manual install or picking parts (Windows:
.venv\Scripts\pip):pip install -e ".[audio]" # tempo/key + light melody pip install -e ".[audio,audio-accurate]" # + CREPE (accurate melody) pip install -e ".[audio-chords]" # chords: then also run pip install --no-deps basic-pitch==0.4.0 # (skips its TensorFlow requirement)Configure FL Studio — Options > MIDI Settings:
Enable
FLStudioMCP RXas an input, set its controller type to FLStudioMCP, and give it a port number.Select
FLStudioMCP TXin the output list and give it the same port number. Outputs have no Enable button; setting the port is what activates it. Leave Send master sync off.View > Script output should show
[FLStudioMCP] Ready.
Start the bridge daemon (recommended) so the MIDI port is held by a stable process:
scripts\start_daemon.bat :: Windows: double-click, keep the window open fl-studio-mcp-daemon # macOSRegister the server with Claude Code or Claude Desktop. On Windows, use the full
...\.venv\Scripts\fl-studio-mcp.exepath the installer printed instead offl-studio-mcp.Claude Code: just ask Claude, for example:
Add the fl-studio MCP server for all my projects:
<path to fl-studio-mcp>with env FLSTUDIO_MCP_TRANSPORT=tcpClaude Desktop, add it to the config file:
Windows:
%APPDATA%\Claude\claude_desktop_config.jsonmacOS:
~/Library/Application Support/Claude/claude_desktop_config.json{ "mcpServers": { "fl-studio": { "command": "fl-studio-mcp", "env": { "FLSTUDIO_MCP_TRANSPORT": "tcp" } } } }tcproutes through the daemon, which works regardless of how Claude launches the server. Omit the env var to let the server open the MIDI ports directly instead.Arm the note bridge (per session) — open the piano roll and choose Tools > Scripting > MCP > MCP Apply from its menu once, so note-writing works.
On macOS, the note bridge re-triggers the armed script with
Cmd+Opt+Y. Grant Accessibility permission to the app running the MCP server or daemon, for example Terminal, iTerm, Claude Desktop, or Cursor: System Settings > Privacy & Security > Accessibility.
Verify the connection by asking Claude to call fl_ping.
After updating an existing installation, restart the bridge daemon and reconnect your MCP client so both processes load the new source. Dry-run is scoped to one MCP server process and resets on reconnect. See bridge correctness regressions for numeric JSON compatibility, dry-run behavior, and localized parameter names.
Troubleshooting
Symptom | Fix |
Virtual MIDI ports not found / not detected | The two ports must be named exactly |
| Open FL Studio once so it creates its user-data folder. If you moved that folder (Options > File settings > User data folder), |
| The commands live in the repo's |
Python crashes on start / MIDI library fails to load (Windows) | Install Python 3.12 from python.org, delete the |
No | The controller isn't registered: set the |
Claude can't reach FL / | Make sure the daemon is running ( |
| Usually happens after changing MIDI Settings while the script is running. Open View > Script output, select the FLStudioMCP tab and click Reload script (or restart FL Studio). Also check that the Output port number is on |
Note-writing does nothing | Run |
macOS note-trigger fails | Grant Accessibility permission to the app running the MCP server or daemon, then click the FL Piano roll and try |
Audio tools error or are unavailable | Re-run the installer and answer Y to "Install audio to MIDI?" (or install the extras manually, see Setup step 2). |
The installer stops because the MCP server is running | Claude Desktop or Claude Code is running |
Usage examples
Plain-language prompts:
"Scan my mix and tell me what's wrong."
"Set up a vocal chain on the lead vocal using my plugins."
"Suggest a vintage bass preset from my Serum library."
"Compose an 8-bar melody in D Dorian and write it to the selected channel."
"Export this arrangement to a MIDI file."
"What tempo and key is this track?" (on an audio file)
Architecture
A thin controller script runs inside FL Studio and returns only cheap, raw data; all judgement — diagnosis, calibration, planning — happens server-side. A standalone daemon owns the MIDI port so the server works regardless of how the MCP client is launched. Note authoring uses a generated pyscript bridge: the daemon re-triggers the armed MCP_Apply script with the platform run-last-script shortcut after a brief window force-focus. Every project-modifying tool routes through a snapshot → write → readback → rollback safety layer backed by a persisted change log.
Design notes and findings are in docs/.
License
MIT — see LICENSE.
Status & contributing
Beta — the public 1.0 release. Windows and macOS are supported; Linux contributions are welcome. Issues and pull requests: github.com/rosasynthesiz/flstudio-mcp.
Available Tools
67 toolsfl_analyze_audioAnalyze audio (tempo/key)ARead-onlyIdempotent
Estimate tempo + key (+ duration, beats, onsets) of an audio file. Pure offline analysis -- does NOT touch FL. Key is ESTIMATED.
Inputs: path (required). Returns: object
fl_apply_compression_intentApply a compression intentA
Compress via Fruity Limiter (COMP section) or FabFilter Pro-C. ALWAYS sets ratio AND threshold together; ratio/attack/release/makeup (+ Pro-C Style) per intent, as ONE rollback unit. When level_aware and the track is playing, threshold is set relative to the MEASURED peak (a smart starting point, not exact gain-reduction); stopped -> preset fallback + a note. Returns readback + the measured level / chosen threshold.
Inputs: track (required), slot (required), intent (required), intensity, +1 more. Returns: object
fl_apply_delay_intentApply a delay intentA
Musical delay moves on a Fruity Delay (time division / feedback / wet / feedback-cut), as one undo-able group. Feedback is clamped <=100% unless intensity>0.9 (warns on self-oscillation risk). Returns readback strings.
Inputs: track (required), slot (required), intent (required), intensity. Returns: object
fl_apply_eq_intentApply an EQ mixing intentA
Apply a musical EQ move on a Fruity Parametric EQ 2 using a free band. Sets type/freq/gain/width as one undo-able group; returns the band used and FL's readback strings. Revert with fl_rollback_last_change.
Inputs: track (required), slot (required), intent (required), intensity. Returns: object
fl_apply_mix_fixApply a Mix Doctor fix (gated)A
Apply ONE Mix Doctor fix via the safety layer: snapshot -> write -> FRESH readback -> rollback-able with fl_rollback_last_change.
Call this ONLY after the user approves the exact change in conversation (Mix Doctor never auto-applies). 'trim_volume' sets a mixer track's fader to target_db. For grouping use fl_group_tracks; for EQ use fl_apply_eq_intent.
Inputs: kind (required), track, target_db. Returns: object
fl_apply_reverb_intentApply a reverb intentA
Musical reverb moves on a Fruity Reeverb 2 (decay/wet/high-cut), as one undo-able group. Returns readback strings. Revert: fl_rollback_last_change.
Inputs: track (required), slot (required), intent (required), intensity. Returns: object
fl_arrange_add_markerAdd a section marker at a barA
Add a named timeline marker at a bar (intro/verse/chorus/drop).
Inputs: bar (required), name (required). Returns: object
fl_arrange_clone_patternClone a pattern (copies notes)A
Clone a pattern (copies its notes) and rename the clone -- e.g. for verse -> verse2 variations.
Inputs: src (required), new_name (required). Returns: object
fl_arrange_new_patternNew named pattern (selects it)A
Create + select + name the next empty pattern. After this, the note bridge (fl_write_piano_roll_notes) writes INTO this pattern.
Inputs: name (required). Returns: object
fl_arrange_select_channelSelect channel (note-bridge target)A
Make a channel the active selection so the note bridge (fl_write_piano_roll_notes) writes INTO it. Use before writing each instrument's notes in a section (drums -> ch X, bass -> ch Y, ...).
Inputs: channel (required). Returns: object
fl_clear_mute_soloClear all mutes + solosA
Unmute and unsolo every mixer track (reset). The universal undo for the bulk solo/mute tools.
Inputs: no named parameters. Returns: object
fl_detect_cleanup_candidatesDetect cleanup candidates (read-only)ARead-onlyIdempotent
Flag (do NOT touch) empty channels + unused mixer tracks, each with a reason. Judgement is computed server-side from cheap controller reads. Channel emptiness is a name heuristic; unused-track detection is reliable.
Inputs: no named parameters. Returns: object
fl_diagnose_mixDiagnose the mix (Mix Doctor)ARead-onlyIdempotent
Scan the WHOLE mix and report problems + proposed fixes. READ-ONLY.
Transparent threshold rules (clipping, headroom, level imbalance, missing high-pass, ungrouped tracks, EQ clashes) on a thin paginated snapshot; returns findings (severity + exact evidence) + concrete proposals.
IMPORTANT: this samples peaks over only ~1.2s -- one MOMENT of the song, so it can MISS clipping in a drop/chorus that isn't playing right now. For full-song-accurate levels use WATCH mode: fl_mix_watch_start -> play the whole song -> fl_mix_watch_stop. If stopped, level rules are skipped (needs_playback). Applies nothing.
Inputs: no named parameters. Returns: object
fl_export_midiExport arrangement to .midA
Write a type-1 multi-track .mid from an arrangement spec. YOU (Claude) generate the whole arrangement -- multiple named tracks, each with notes {pitch, start_bars, length_bars, velocity} across all sections -- and this writes ONE .mid. Bypasses the note-bridge's one-pattern + MCP_Apply limits.
Does NOT touch FL: IMPORT the file yourself (FL: File > Import > MIDI file, or drag it into the playlist). FL won't auto-load instruments -- assign a channel to each imported track. Returns the saved file path.
Inputs: tracks (required), bpm, output_path, beats_per_bar. Returns: object
fl_extract_melodyExtract melody from audio (pyin/CREPE)ARead-onlyIdempotent
Transcribe a monophonic melody to quantized notes; engine-selectable (CREPE = accurate/heavy, pyin = light). Returns ALL notes with confidence
a
keptflag; bridge_notes holds only the confident notes, ready for fl_write_piano_roll_notes. Does NOT write to FL -- review first.
Inputs: path (required), bpm, engine, min_conf. Returns: object
fl_gain_stageGain staging assistant (Mix Doctor)ARead-onlyIdempotent
Propose per-track fader trims so each track's peak sits in a healthy band (~-12..-6 dBFS, aim -9) and the Master keeps -3..-6 dB headroom. READ-ONLY proposals -- apply approved ones via fl_apply_mix_fix (rollback).
Uses FULL-SONG peaks from a recent watch (fl_mix_watch_start -> play -> fl_mix_watch_stop) when available; else a ~1.2s snapshot (prefer watch). FL's fader is POST-chain, so this sets a track's OUTPUT level, not a true pre-plugin input trim.
Inputs: no named parameters. Returns: object
fl_get_channel_routingGet channel->mixer routingARead-onlyIdempotent
Which mixer track each channel-rack channel is linked to: {total, channels:[{channel, name, target_mixer_track, target_name}]}.
Inputs: no named parameters. Returns: object
fl_get_channel_stateGet channel stateARead-onlyIdempotent
All channel-rack channels (index, name, volume, pan, mute, solo).
Inputs: no named parameters. Returns: object
fl_get_mixer_stateGet mixer stateARead-onlyIdempotent
All mixer tracks (index, name, volume, pan, mute, solo). Names in this overview are truncated; use a single-track read for the full name.
Inputs: no named parameters. Returns: object
fl_get_play_stateGet play stateARead-onlyIdempotent
Return whether FL is currently playing and / or recording.
Inputs: no named parameters. Returns: object
fl_get_project_stateGet project stateBRead-onlyIdempotent
Tempo, transport state, pattern/channel/mixer counts.
Inputs: no named parameters. Returns: object
fl_get_routingGet mixer track routingARead-onlyIdempotent
Which destination tracks this mixer track sends to: {track, name, routes_to:[{dst, dst_name, level?}]}.
Inputs: track (required). Returns: object
fl_get_routing_allGet full routing matrixARead-onlyIdempotent
Routing for every mixer track (paginated under the hood, returned whole): {total, routing:[{i, name, routes_to:[...]}]}.
Inputs: no named parameters. Returns: object
fl_get_song_positionGet song position (beats)ARead-onlyIdempotent
Return the current playhead position in beats from the song start.
Inputs: no named parameters. Returns: object
fl_get_tempoGet tempo (BPM)ARead-onlyIdempotent
Return the current FL Studio project tempo in beats per minute.
Inputs: no named parameters. Returns: object
fl_get_track_levelGet track level (dB)ARead-onlyIdempotent
Measure a mixer track's level by sampling meter peaks over a short window. Requires PLAYBACK -- returns playing=False (avg/peak null) when stopped/silent. {track, playing, avg_db, peak_db}.
Inputs: track (required), samples. Returns: object
fl_group_tracksGroup tracks into a busAIdempotent
Group sources into a bus, EXCLUSIVELY: each source -> bus ON and its direct -> Master OFF; bus -> Master ON; optional bus rename. Applied as ONE rollback unit -- fl_rollback_last_change undoes the whole grouping.
Inputs: sources (required), bus (required), name. Returns: object
fl_list_chainsList genre chainsARead-onlyIdempotent
List the built-in genre processing-chain recipes (vocal, drum_bus, bass, master) and their ordered steps.
Inputs: no named parameters. Returns: object
fl_list_installed_pluginsList installed plugins (FL DB on disk)ARead-onlyIdempotent
Read FL's installed-plugin DATABASE from disk (the .fst shortcuts FL writes for every scanned plugin) -> a de-duped, categorized list of what you OWN. Bypasses the FL API (which only sees LOADED plugins). FL still can't LOAD these -- it's for library-aware suggestions. effects_by_role is a rough keyword grouping (Claude should apply its own plugin knowledge). Read-only (directory listing only).
Inputs: kind. Returns: object
fl_list_presetsList presets (from disk)ARead-onlyIdempotent
Read preset NAMES from disk: FL Presets\ (per-plugin 'Plugin presets', plus Channel/Mixer presets) + Serum 2 Presets (.serumpreset). With NO filter -> a SUMMARY (which plugins have presets + counts). With plugin_filter -> that plugin's full preset list. Read-only. FL can't LOAD presets via the API -- this is for suggestions (you load the named preset, then Claude can tweak it).
Inputs: plugin_filter. Returns: object
fl_mix_watch_startStart full-song peak watch (Mix Doctor)ARead-onlyIdempotent
Begin a peak-HOLD watch: continuously sample every mixer track's peak, keeping a RUNNING MAX per track, until fl_mix_watch_stop. Tell the user to PLAY the whole song (or at least the loudest section / the drop) while this runs -- then stop for full-song-accurate level diagnosis. Read-only.
Inputs: interval_ms. Returns: object
fl_mix_watch_statusPeak watch status (Mix Doctor)ARead-onlyIdempotent
Is a peak watch running, and for how long / how many polls so far?
Inputs: no named parameters. Returns: object
fl_mix_watch_stopStop peak watch + diagnose (Mix Doctor)ARead-onlyIdempotent
Stop the peak watch and diagnose on the FULL-SONG running-max peaks captured across the whole watch (accurate clipping/headroom/imbalance vs the ~1.2s snapshot). Read-only -- proposes fixes, applies nothing.
Inputs: no named parameters. Returns: object
fl_mute_tracksMute a group of tracksA
Mute a group of tracks (leaves the others as they are). Use category or explicit tracks. One rollback unit; reverse with fl_clear_mute_solo.
Inputs: category, tracks. Returns: object
fl_pingPing FL StudioARead-onlyIdempotent
Check that FL Studio is running and the controller script is loaded.
Returns the controller's reported FL Studio version, the age of the last heartbeat in seconds, and the MIDI port names in use. Call this first when something seems wrong.
Inputs: no named parameters. Returns: object
fl_playPlayAIdempotent
Start playback. Idempotent — calling while already playing is a no-op.
Inputs: no named parameters. Returns: object
fl_plugin_get_paramsGet plugin parametersARead-onlyIdempotent
Every named parameter of the plugin in this slot: index, name, normalised value (0..1) and FL's display string (e.g. '3.6dB', '500Hz'). Returns {"total", "params":[{"i","name","v","s"}, ...]}.
Inputs: track (required), slot (required). Returns: object
fl_plugin_listList plugins on a mixer trackARead-onlyIdempotent
List the filled effect slots (0-9) on a mixer track, with plugin names.
We cannot load NEW plugins (FL API limit) -- this only reports plugins already present in the project.
Inputs: track (required). Returns: object
fl_plugin_set_paramSet plugin parameterAIdempotent
Set one plugin parameter (normalised 0..1). param may be an
index or a name; names are resolved from the live param list. The
change is logged and undo-able via fl_rollback_last_change. Returns
before/after plus the resolved {index, name}.
Inputs: track (required), slot (required), param (required), value (required). Returns: object
fl_quantize_patternQuantize piano-roll notesA
Quantize the notes ALREADY in the open Piano roll: reads the score, snaps note starts (and optionally lengths) to the grid, rewrites -- via the pyscript bridge, no dialog. Needs the Piano roll open + MCP_Apply armed once this session (same setup as note writing).
Inputs: grid_bars, snap_ends. Returns: object
fl_recordToggle recordADestructive
Toggle FL Studio's record-arm state.
Inputs: no named parameters. Returns: object
fl_reference_matchReference match (level/balance)ARead-onlyIdempotent
Compare your mix's LEVEL + rough tonal BALANCE to a reference track. READ-ONLY. Analyzes the reference FILE (overall level + low/mid/high spectral-band shares) and your mix (Master peak for level + a ROUGH name-based band estimate). HONEST: a level/balance compare, NOT a spectral match -- FL doesn't expose its output audio, so the your-mix balance is estimated from track names + peaks. Suggests adjustments; applies nothing.
Inputs: reference_audio_path (required). Returns: object
fl_rollback_last_changeRollback last changeADestructive
Undo the most recent write by replaying its pre-change snapshot.
Inputs: no named parameters. Returns: object
fl_set_channel_colorColor channelsA
Set the color of channel-rack channels (separate from mixer-track color). Target by index or name substring. ONE rollback unit -- fl_rollback_last_change reverts it.
Inputs: color (required), channels. Returns: object
fl_set_channel_muteSet channel muteAIdempotent
Mute or unmute a channel-rack channel (state=True mutes).
Inputs: channel (required), state (required). Returns: object
fl_set_channel_panSet channel panAIdempotent
Set a channel-rack channel's pan position (-1 left .. +1 right).
Inputs: channel (required), value (required). Returns: object
fl_set_channel_soloSet channel soloAIdempotent
Solo or unsolo a channel-rack channel (state=True solos).
Inputs: channel (required), state (required). Returns: object
fl_set_channel_volumeSet channel volumeAIdempotent
Set a channel-rack channel's volume. unit='db' uses 0.8=unity (0 dB).
Inputs: channel (required), value (required), unit. Returns: object
fl_set_dry_runSet dry-run modeAIdempotent
When on, write tools return a 'planned' preview without changing FL.
Inputs: enabled (required). Returns: object
fl_set_mixer_muteSet mixer track muteBIdempotent
Mute or unmute a mixer track (state=True mutes).
Inputs: track (required), state (required). Returns: object
fl_set_mixer_nameSet mixer track nameAIdempotent
Rename a mixer track.
Inputs: track (required), name (required). Returns: object
fl_set_mixer_panSet mixer track panAIdempotent
Set a mixer track's pan position (-1 left .. +1 right).
Inputs: track (required), value (required). Returns: object
fl_set_mixer_soloSet mixer track soloBIdempotent
Solo or unsolo a mixer track (state=True solos).
Inputs: track (required), state (required). Returns: object
fl_set_mixer_volumeSet mixer track volumeAIdempotent
Set a mixer track volume. unit='db' uses 0.8=unity (0 dB).
Inputs: track (required), value (required), unit. Returns: object
fl_set_routeSet mixer routing (src -> dst)AIdempotent
Enable/disable a send from src -> dst (calls afterRoutingChanged on the FL side). Snapshot + readback; undo with fl_rollback_last_change.
Inputs: src (required), dst (required), enabled. Returns: object
fl_set_song_positionSet song position (beats)AIdempotent
Move the playhead to the given beat position.
Inputs: beats (required). Returns: object
fl_set_tempoSet tempo (BPM)AIdempotent
Set the FL Studio project tempo. Range is 10-999 BPM (FL's own limits).
Inputs: bpm (required). Returns: object
fl_set_track_colorColor mixer tracksA
Set the color of mixer tracks. Pick targets by category ('drums', 'bass', ...) or an explicit tracks list; choose a color by name or hex. All writes are ONE rollback unit -- fl_rollback_last_change reverts them. (Master is never colored.)
Inputs: color (required), category, tracks. Returns: object
fl_setup_chainSet up a genre chain (plan)ARead-onlyIdempotent
Plan a genre-appropriate processing chain over a track's EXISTING plugins. READ-ONLY plan: returns the ordered intent calls (each with the matched plugin + slot) and which steps are MISSING because the needed plugin isn't loaded (FL can't load plugins -- add those manually). After the user approves, apply each step by calling its 'apply' tool+args (fl_apply_eq_intent / fl_apply_compression_intent / fl_apply_reverb_intent -- each logged + rollback-able). e.g. vocal: HP -> comp -> presence -> air -> reverb.
Inputs: track (required), chain_type (required). Returns: object
fl_solo_tracksSolo a group of tracksA
Isolate a group so only it is audible -- mutes every OTHER (non-Master) track. Use category ('drums', etc.) or explicit tracks. Implemented as mute-the-rest (reliable; FL's multi-solo is inconsistent). Reverse with fl_clear_mute_solo. One rollback unit.
Inputs: category, tracks. Returns: object
fl_stopStopAIdempotent
Stop playback. Idempotent.
Inputs: no named parameters. Returns: object
fl_suggest_presetSuggest a preset by descriptionARead-onlyIdempotent
Suggest presets from YOUR library matching a description, for a given plugin. Reads the plugin's preset NAMES from disk + ranks by name match. Name-only (can't hear the sound) -- apply your own knowledge of preset naming. FL can't LOAD presets via the API: recommend which to load in the plugin manually; AFTER the user loads it you can tweak its params via fl_plugin_set_param / fl_apply_*_intent.
Inputs: description (required), plugin (required). Returns: object
fl_take_snapshotTake snapshotARead-onlyIdempotent
Read current state for a scope (for your own before/after diffing).
Inputs: scope (required). Returns: object
fl_toggle_playToggle playA
Toggle between play and stop, mirroring the spacebar in FL.
Inputs: no named parameters. Returns: object
fl_write_piano_roll_notesWrite piano-roll notesADestructive
Write notes into the currently-open FL Piano roll.
Each note: {pitch (MIDI), time_bars, length_bars, velocity 0-1}. Set quantize (grid in bars) to snap note starts to a grid before writing. Setup: open the Piano roll and run 'MCP_Apply' once from its Scripting menu (so Ctrl+Alt+Y targets it). mode='replace' clears first.
Inputs: notes (required), mode, quantize. Returns: object
fl_write_raga_chordsWrite raga/scale CHORDSADestructive
Write CHORDS / a progression (stacked notes sharing start times) into the selected channel via the bridge. YOU stack chord tones drawn from the raga/scale (give simultaneous notes the SAME time_bars). Tool selects the channel + writes. SHOW the user the chords BEFORE calling.
Inputs: notes (required), raga, root, channel, +1 more. Returns: object
fl_write_raga_melodyWrite a raga/scale MELODYADestructive
Write a MELODY (single-line, sequential notes) into the selected channel via the piano-roll bridge. YOU (Claude) generate the swaras for the named raga/root -> MIDI notes (use the proper aarohana/avarohana; respect the raga's allowed swaras); this tool only selects the channel + writes. SHOW the user the notes/swaras BEFORE calling. Needs the Piano roll open + MCP_Apply armed once this session (see the note-bridge setup).
Inputs: notes (required), raga, root, channel, +1 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 67 tools
Most tools have clearly distinct purposes, but the sheer number (67) creates some potential confusion, especially among similar-sounding tools like fl_get_channel_routing, fl_get_routing, fl_get_routing_all. However, descriptions help differentiate them.
All tools follow a consistent fl_verb_noun pattern using snake_case, making it easy to predict tool names. Naming is highly uniform throughout the set.
With 67 tools, the server is excessively large for a typical MCP server. While it covers many aspects of FL Studio, the scope is too broad, making it difficult for agents to navigate and select the right tool efficiently.
The toolset covers a wide range of FL Studio operations (project info, mixer, channel rack, piano roll, mixing effects, etc.), but notable gaps exist, such as no tool for loading plugins or handling automation, limiting full workflow coverage.
Maintenance
Related MCP Connectors
Compose, mix, master and export in Logic Pro, REAPER or Ableton Live by talking to an AI engineer.
AI mixing and mastering: analyze your mixes, run DSP autofix, render stems, and master tracks.
AI mixing and mastering in the chat: check a song, mix your stems, change the mix in plain words.
Score video, make music as an agent: 100+ AI instruments play your MIDI, audio, stems, Logic/Ableton
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to control FL Studio on Windows through a local MCP server without cloud dependencies. Bridges MCP clients to FL Studio's Python scripting environment via file-based IPC for project management, transport control, and UI workflow automation.-
- AlicenseNot gradedqualityDmaintenanceReal-time AI-assisted music production, advanced composition, mixing, and VST coordination for FL Studio via bidirectional MIDI & WebSockets, exposing over 100 tools for comprehensive DAW control.9MIT
- AlicenseCqualityCmaintenanceGives AI assistants full control of FL Studio through its scripting API, enabling project editing, mixing, piano roll composition, MIDI export, and plugin automation without touching the mouse or keyboard.572MIT
- AlicenseNot gradedqualityCmaintenanceEnables Claude Desktop to drive FL Studio 2025 and 2026 through natural language, diagnosing and repairing mixes, configuring plugins, writing notes and chords in any scale, exporting arrangements to MIDI, and analyzing audio for tempo, key, and melody.MIT