FL Studio MCP Server
Enables 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.
README
mcp-flstudio
Official release label: Pré-BETA Complete MCP-serveur-FL-Studio2025
A canonical local-core MCP (Model Context Protocol) server for FL Studio on Windows: no cloud relay for the published core surface, explicit extension boundaries for non-local capabilities, and a public CLI/runtime that can be packaged and shipped cleanly.
Works with Claude Desktop, VS Code Copilot, Codex, and any other MCP-compatible client.
Architecture
┌─────────────────────────────────────────────────────────┐
│ MCP Client (Claude Desktop / VS Code / Codex) │
└────────────────────┬────────────────────────────────────┘
│ JSON-RPC over stdio
┌────────────────────▼────────────────────────────────────┐
│ MCP Server (Node.js / TypeScript) │
│ │
│ ┌──────────────────┐ ┌──────────────────────────────┐ │
│ │ WindowsDesktop │ │ LocalMailbox Bridge │ │
│ │ Bridge │ │ │ │
│ │ PowerShell COM │ │ inbox/ ←── requests (.json) │ │
│ │ (fallback only) │ │ outbox/ ──→ responses (.json)│ │
│ └──────────────────┘ └──────────────┬───────────────┘ │
│ ┌──────────────────────────────────┐ │ │
│ │ LocalHelper Backend (optional) │ │ │
│ │ PowerShell — render / playlist │ │ │
│ └──────────────────────────────────┘ │ │
└────────────────────────────────────────┼────────────────┘
│ file IPC
┌────────────────────────────────────────▼────────────────┐
│ FL Studio (Python MIDI script companion) │
│ FLMcpBridge.py — runs inside FL Studio process │
│ Reads inbox → executes FL API → writes outbox │
└─────────────────────────────────────────────────────────┘
Three-tier bridge — fallback flow
flowchart TD
Client([MCP Client]) -->|stdio JSON-RPC| Server[MCP Server]
Server --> D{FL Studio running?}
D -- No --> ERR1[Error: FL_NOT_RUNNING]
D -- Yes --> C{Companion active?\nheartbeat fresh}
C -- Yes --> MB[LocalMailbox Bridge\ninbox → outbox file IPC]
MB -->|timeout| CACHE[Return cached state\nfrom last heartbeat]
C -- "No, desktop-capable cmd" --> DB[WindowsDesktop Bridge\nPowerShell SendKeys]
DB --> FL[FL Studio process]
C -- "No, mailbox-only cmd" --> ERR2[Error: COMPANION_NOT_RUNNING]
MB --> HELPER{Helper configured?}
HELPER -- Yes --> HP[LocalHelper Backend\nPowerShell render / playlist]
HELPER -- No --> MB2[Mailbox result only]
HP --> ENRICH[Enriched response]
Mailbox IPC — request lifecycle
sequenceDiagram
participant S as MCP Server
participant FS as File System
participant C as FL Companion
S->>FS: write inbox/<uuid>.json (atomic)
loop OnIdle / OnMidiIn callback
C->>FS: scan inbox/ for .json files
FS-->>C: inbox/<uuid>.json found
C->>C: execute FL Studio API
C->>FS: write outbox/<uuid>.json (atomic)
end
loop poll every 150 ms
S->>FS: check outbox/<uuid>.json
FS-->>S: response found
end
S->>FS: delete outbox/<uuid>.json
S-->>S: return response to client
Components
| Component | Runtime | Location |
|---|---|---|
| MCP Server | Node.js ≥ 20 | src/ → dist/ |
| Python Companion | Python 3.x (FL Studio built-in) | companion/fl_studio/FLMcpBridge.py |
| Helper Script (optional) | PowerShell | user-defined, set via FL_MCP_HELPER_SCRIPT |
Installation
Prerequisites
- Windows 10 / 11
- FL Studio (any recent version with MIDI scripting)
- Node.js ≥ 20
- PowerShell 5+ (pre-installed on Windows)
1 — Build the MCP server
git clone https://github.com/your-org/mcp-flstudio
cd mcp-flstudio
npm install
npm run build
The compiled public CLI is:
node dist/cli/index.js help
or, once installed from npm:
mcp-flstudio help
2 — Install the Python companion in FL Studio
Deploy the companion into the FL Studio MIDI scripts folder:
npm run deploy:companion
or with the public CLI:
node dist/cli/index.js deploy-companion
This installs:
Documents\Image-Line\FL Studio\Settings\Hardware\FLMcpBridge\device_FLMcpBridge.py
Documents\Image-Line\FL Studio\Settings\Hardware\FLMcpBridge\FLMcpBridge.py
The deployed bootstrap now uses this runtime root by default:
Documents\Image-Line\FL Studio\Settings\Hardware\FLMcpBridge\runtime
The Node server auto-detects that deployed runtime before falling back to %LOCALAPPDATA%\FLStudioMcpBridge, so FL_MCP_BRIDGE_DIR is now an override rather than a requirement.
Then in FL Studio:
- Open Options → MIDI Settings
- Create or select a virtual MIDI port named FLMcpBridge (loopMIDI is the recommended local setup)
- Set Input = FLMcpBridge, Controller type = FLMcpBridge, Port = 10
- Prefer Output = (none) for the FLMcpBridge script device. If you need an FL Studio MIDI output, use a second dedicated loopMIDI port instead of reusing the same one.
- Click Update MIDI scripts / Mettre a jour scripts MIDI
- Restart FL Studio if the script does not reload immediately
The companion now keeps MIDI master sync disabled by default to avoid transport feedback loops when the same loopMIDI port is used for both input and output.
If playback makes the BPM dip or fluctuate, inspect the FL Studio MIDI routing first: repeated OnMidiIn activity while transport starts usually means the loopback port is still receiving transport or clock data. The most reliable setup is one input-only script port for FLMcpBridge, with no FL output assigned to that same virtual port.
The play/pause loop reported during validation is now resolved in the default deployed runtime: inbound MIDI callbacks are swallowed by the script, and mailbox servicing stays on OnIdle / OnUpdateMeters.
The companion writes its mailbox state and heartbeat to:
Documents\Image-Line\FL Studio\Settings\Hardware\FLMcpBridge\runtime\state.json
3 — Configure your MCP client
Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"flstudio-local": {
"command": "node",
"args": ["C:/path/to/mcp-flstudio/dist/cli/index.js", "serve"]
}
}
}
VS Code (.vscode/mcp.json — already included in this repo):
{
"servers": {
"flstudio-local": {
"type": "stdio",
"command": "node",
"args": ["${workspaceFolder}/dist/cli/index.js", "serve"]
}
}
}
See config/ for additional examples (Codex, PowerShell helper).
Configuration
All settings are environment variables. Copy .env.example to .env and adjust. The server and CLI now load .env automatically from the working directory, or from FL_MCP_ENV_FILE when set.
| Variable | Default | Description |
|---|---|---|
FL_MCP_BRIDGE_DIR |
auto-detect deployed Hardware\FLMcpBridge\runtime, then %LOCALAPPDATA%\FLStudioMcpBridge |
Root directory for all bridge files |
FL_MCP_HELPER_DIR |
<bridge_dir>\helper |
Root directory for helper request and snapshot files |
FL_MCP_LOG_FILE |
<bridge_dir>\bridge.log |
Structured JSON log path |
FL_MCP_LOG_LEVEL |
info |
debug / info / warn / error |
FL_MCP_SAFE_MODE |
true |
Enables operation guards |
FL_MCP_RESPONSE_TIMEOUT_MS |
8000 |
Default mailbox timeout (ms) |
FL_MCP_HEARTBEAT_TIMEOUT_MS |
15000 |
Companion considered dead after (ms) |
FL_MCP_STALE_REQUEST_AGE_MS |
300000 |
Auto-cleanup age for orphaned requests |
FL_MCP_WINDOW_TITLE |
FL Studio |
Window title for focus automation |
FL_MCP_HELPER_SCRIPT |
(unset) | Path to optional PowerShell helper script |
FL_MCP_HELPER_TIMEOUT_MS |
45000 |
Helper script timeout (ms) |
Available Tools
The live server only registers implemented tools. The canonical catalog remains the source of truth, and any non-local command stays out of the published local-core registry.
Compatibility aliases kept across 1.x:
fl_save_project->session_save_projectfl_undo->session_undofl_redo->session_redo
session_clear_undo_history is retained as an extension-only compatibility utility and is not part of the canonical published surface.
Status & diagnostics
| Tool | Description |
|---|---|
fl_ping |
Check whether FL Studio and the companion are reachable |
fl_get_status |
Full status: process, companion, health, transport |
fl_get_version |
FL Studio version and build number |
fl_get_project_name |
Current project name |
fl_get_project_path |
Current project file path |
fl_get_project_modified_state |
Whether there are unsaved changes |
fl_get_active_window |
Targeted FL Studio window title |
fl_get_focus_state |
Whether FL Studio is focused |
fl_get_last_error |
Last recorded bridge error |
fl_get_environment_info |
Runtime environment summary |
fl_get_timebase |
Project PPQ / timebase |
fl_get_ui_state |
Current FL Studio UI visibility summary |
Project overview
| Tool | Description |
|---|---|
project_get_info |
Project name, tempo, channel/mixer/playlist counts |
project_get_summary |
Full project state snapshot |
project_get_stats |
Derived statistics (muted channels, clip counts…) |
project_get_structure |
Derived arrangements / sections / markers |
project_get_selection |
Current playlist selection |
project_get_current_arrangement |
Active arrangement metadata |
project_get_open_windows |
Active FL window + UI state |
project_get_markers |
Playlist markers |
project_get_channel_inventory |
All channels with state |
project_get_mixer_inventory |
All mixer tracks with state |
project_get_playlist_inventory |
Playlist clips, tracks, and markers |
project_get_recent_actions |
Latest MCP actions in this session |
Transport
| Tool | Inputs | Description |
|---|---|---|
transport_play |
— | Start playback |
transport_stop |
— | Stop playback |
transport_pause |
— | Pause playback |
transport_get_status |
— | Playing / paused / stopped / recording |
transport_get_song_position |
— | Position in ticks |
transport_set_song_position |
ticks |
Move playhead |
transport_jump_to_bar |
bar |
Jump to bar number |
transport_jump_to_tick |
tick |
Jump to exact tick |
transport_get_tempo |
— | Current BPM |
transport_set_tempo |
bpm (10–300) |
Set tempo |
transport_nudge_tempo |
delta_bpm |
Offset current BPM |
transport_rewind |
amount_ticks? |
Move playhead backward |
transport_fast_forward |
amount_ticks? |
Move playhead forward |
transport_start_from_beginning |
play_after? |
Reset to bar 1 and optionally play |
transport_get_time_signature |
— | Current time signature |
Channels
| Tool | Inputs | Description |
|---|---|---|
channel_list |
— | All channels with name, volume, mute state |
channel_get |
channel_index |
Single channel summary |
channel_find_by_name |
name |
Case-insensitive channel lookup |
channel_set_volume |
channel_index, value (0–1) |
Set channel volume |
channel_mute |
channel, muted |
Mute / unmute |
channel_unmute |
channel_index |
Unmute channel |
Mixer
| Tool | Inputs | Description |
|---|---|---|
mixer_list_tracks |
— | All mixer tracks |
mixer_get_track |
track_index |
Single mixer track summary |
mixer_set_volume |
track_index, value (0–1) |
Set track volume |
mixer_mute |
track, muted |
Mute / unmute |
Playlist
| Tool | Inputs | Description |
|---|---|---|
playlist_get_clips |
— | Playlist inventory enriched by the helper backend when available |
playlist_list_tracks |
— | Derived playlist track list |
playlist_get_track |
track_index |
Single playlist track summary |
Piano Roll
| Tool | Inputs | Description |
|---|---|---|
pianoroll_get_notes |
channel? |
All notes in the current piano roll |
pianoroll_add_note |
pitch, start, length, velocity?, channel? |
Add a note |
pianoroll_quantize |
channel?, amount? (0–1) |
Quantize notes |
Plugins
| Tool | Inputs | Description |
|---|---|---|
plugin_set_parameter |
target, parameter, value (0–1) |
Set a plugin parameter |
Session management
| Tool | Inputs | Description |
|---|---|---|
fl_save_project / session_save_project |
— | Save the current project |
fl_undo / session_undo |
— | Undo last action |
fl_redo / session_redo |
— | Redo |
session_save_checkpoint |
label |
Named state snapshot |
session_list_checkpoints |
— | All checkpoints |
session_delete_checkpoint |
checkpoint_id |
Delete a checkpoint |
session_get_undo_history |
— | Recent undo/redo entries |
session_clear_undo_history |
— | Remove undo/redo from audit log |
session_get_audit_log |
limit? |
Full audit log |
session_clear_audit_log |
— | Clear audit log |
session_begin_transaction |
label? |
Open a logical transaction |
session_commit_transaction |
transaction_id |
Commit |
session_abort_transaction |
transaction_id |
Abort |
session_get_transaction_state |
transaction_id |
Transaction status |
Render
| Tool | Inputs | Description |
|---|---|---|
render_preview_wav |
outputPath? |
Trigger a local WAV render via the helper backend |
Resources (MCP)
| URI | Description |
|---|---|
fl://status/current |
Current FL Studio status (JSON) |
fl://project/current |
Current project summary (JSON) |
fl://channels/list |
Channel list (JSON) |
fl://mixer/{track} |
Mixer track detail (JSON) |
fl://catalog/tools |
Full tool catalog |
fl://catalog/domain/{domain} |
Tools for one domain |
fl://catalog/tool/{name} |
Single tool definition |
fl://catalog/coverage |
Generated coverage report: canonical / published / alias / missing |
Prompts (MCP)
| Name | Args | Description |
|---|---|---|
arrange-trap-beat |
style, bars |
Inspect session and propose an arrangement |
audit-session-before-render |
focus |
Pre-render checklist |
clean-up-low-end |
bassBus |
Low-end cleanup workflow |
Health states
fl_get_status → health field
| State | Meaning |
|---|---|
ready |
FL Studio running + companion active and sending heartbeats |
degraded |
FL Studio running, companion detected but heartbeat stale (> 15 s) |
offline |
FL Studio process not found |
Diagnostics
# Print the resolved configuration
npm run debug:config
# or
node dist/cli/index.js debug-config
# Inspect current bridge state (companion heartbeat, pending requests)
npm run debug:state
# or
node dist/cli/index.js debug-state
# Print canonical catalog coverage vs live registry
npm run catalog:coverage
# Verify the companion end-to-end
npm run verify
# Generate the full tool-by-tool checklist
npm run functional:checklist
# Run the scripted smoke scorecard and publish a Markdown report
npm run evaluate:functional
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
Log output is written to bridge.log in newline-delimited JSON:
# Tail the live log for the resolved bridgeDir (PowerShell)
$bridgeDir = (node dist/cli/index.js debug-config | ConvertFrom-Json).bridgeDir
Get-Content (Join-Path $bridgeDir 'bridge.log') -Wait -Tail 40
Functional validation
Public validation assets now live under docs/validation/:
docs/validation/bridge-runtime-changes.mddocuments the runtime and deployment fixesdocs/validation/mcp-tool-test-checklist.mdlists every registered MCP call and now includes the dated manual validation snapshot from the guided FL Studio campaigndocs/validation/functional-evaluation.plan.jsondefines the scripted smoke suitedocs/validation/functional-evaluation.latest.mdis the latest generated Markdown scorecarddocs/validation/functional-evaluation.latest.htmlis the visual dashboarddocs/validation/functional-evaluation.latest.summary.svgis the release summary visualdocs/validation/functional-evaluation.latest.domains.svgis the domain score visualdocs/validation/functional-evaluation.latest.coverage.svgis the domain coverage visual
The manual snapshot currently records confirmed validation for selection, mute/unmute, solo/unsolo, pan, volume, color, rename, channel-to-mixer routing, mixer enable/disable, and safe transport_play / transport_stop, along with known failures such as channel_set_pitch, transport_toggle_metronome, and the still-inconsistent transport_toggle_loop.
Public command-reference assets now live under docs/reference/:
docs/reference/tool-catalog.en.mdis the English command catalogdocs/reference/tool-catalog.fr.mdis the French command catalogdocs/reference/tool-catalog.csvis the spreadsheet-friendly export of all commandsdocs/reference/tool-catalog.jsonis the machine-readable command inventorydocs/reference/tool-catalog.domains.svgis the command count by domain graphdocs/reference/tool-catalog.coverage.svgis the automated coverage by domain graphdocs/reference/tool-status-board.mdis the working vs incoming/planned status boarddocs/reference/tool-status-board.fr.mdis the dedicated French status boarddocs/reference/tool-status-board.csvis the spreadsheet export of the status boarddocs/reference/tool-status-board.jsonis the machine-readable status boarddocs/reference/tool-status-board.svgis the status distribution graph
Recommended workflow:
npm run functional:checklist
npm run evaluate:functional
npm run docs:catalog
npm run docs:status
The automated plan now covers:
- companion health and transport smoke checks
channel_mutewith automatic state restorationmixer_set_volumewith automatic state restoration- safe
plugin_*inspection calls driven by live target discovery - safe
session_*checkpoint and transaction flows
Limitations
- Windows only — requires PowerShell and FL Studio
transport_stopdesktop fallback is a play/pause toggle; companion required for exact stoptransport_get_song_positionmay returnUNSUPPORTED_COMMANDon FL Studio builds that do not expose bar/beat conversion in the MIDI scripting API- Piano roll quantize exposes full-amount quantize only (FL scripting API limitation)
- Mixer effect plugins are not individually addressable (channel plugins only)
render_preview_wavrequires the optional helper backend script
Development
npm run dev # Run from TypeScript source (tsx, no build needed)
npm run build # Compile TypeScript → dist/
npm run check # Type-check only (no emit)
npm run typecheck # Type-check gate used by CI/prepack
npm run lint # ESLint
npm run lint:fix # ESLint with auto-fix
npm run format # Prettier
npm run functional:checklist
npm run evaluate:functional
npm test # Vitest
npm run test:coverage # With coverage report
npm run ci:check # build + typecheck + lint + test + npm pack --dry-run
Project structure
mcp-flstudio/
├── src/
│ ├── index.ts # MCP server entry point — tool/resource registration
│ ├── config.ts # Environment variable parsing
│ ├── configValidation.ts # Config validation with detailed errors
│ ├── logger.ts # Structured JSON logger (stderr + file)
│ ├── errors.ts # BridgeRuntimeError + toBridgeError()
│ ├── types.ts # Shared TypeScript types
│ ├── env.ts # Optional .env loading
│ ├── publicApi.ts # snake_case public payload normalization
│ ├── server.ts # MCP bootstrap
│ ├── serverRuntime.ts # Shared runtime helpers / tool execution
│ ├── bridge/
│ │ ├── flStudioBridge.ts # Orchestrator — routes across the three tiers
│ │ ├── localMailboxBridge.ts # File-based IPC (inbox/outbox)
│ │ ├── windowsDesktopBridge.ts # PowerShell COM fallback
│ │ └── helperBackend.ts # Optional PowerShell helper (render, playlist)
│ ├── catalog/
│ │ └── loadCatalog.ts # YAML catalog loader + coverage report builder
│ ├── registry/
│ │ ├── definitions.ts # Canonical tool definitions by domain
│ │ └── register.ts # MCP registration factory
│ ├── services/
│ │ └── sessionState.ts # Audit log, checkpoints, transactions
│ ├── cli/
│ │ └── index.ts # Public CLI: serve / debug / verify / deploy
│ └── __tests__/
│ ├── configValidation.test.ts
│ ├── env.test.ts
│ ├── publicApi.test.ts
│ ├── catalog.test.ts
│ ├── packageManifest.test.ts
│ ├── logger.test.ts
│ └── sessionState.test.ts
├── companion/
│ └── fl_studio/
│ ├── device_FLMcpBridge.py # Publishable bootstrap, no hardcoded repo path
│ └── FLMcpBridge.py # FL Studio MIDI script companion runtime
├── config/ # Client configuration examples
├── .github/workflows/ci.yml # Required build/test/package gates
├── dist/ # Compiled output (git-ignored)
└── tools_scoop_mvp_v3 # YAML tool catalog (V3)
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.