fl-studio
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@fl-studioa little more reverb on the guitar"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
FL Codex
Type a request in Codex, such as "a little more reverb on the guitar", and let Codex inspect the actual FL Studio project and adjust exposed plugin knobs.
This is an FL Studio MIDI controller extension + local MCP server for Windows. The extension runs inside FL, selected in MIDI settings > Controller type. It is not a VST DLL to put in a mixer effect slot. Codex supplies the language reasoning; no additional AI API account or API key is needed.
Current status
Experimental. Live connection and discovery have been verified on FL Studio 25.2.5. A real plugin knob write/readback/undo acceptance test is still pending; automated tests use a simulated host. Universal plugin compatibility is not claimed.
Implemented: live track/plugin discovery, paginated parameter inspection, normalized parameter writes with readback, and undo of bridge changes. Live connection verified with FL Studio 25.2.5: version, selection, tracks and loaded-plugin discovery. Automated tests cover guarded edits and undo, MIDI framing, and local TCP/MCP transports. Plugin knob acceptance is recorded in docs/ARCHITECTURE.md.
Scope: loaded effects and instruments that expose parameters through FL's scripting API. Not every visual knob is exposed. Patcher internals need exposed controls. This version does not insert plugins, listen to audio, create notes, or save projects. An existing distortion plugin can be adjusted; adding a new distortion effect is not implemented.
Related MCP server: FL Studio MCP Server
Windows setup
Prerequisites: Windows, FL Studio 2025 (development target: 25.2.5), Python 3.11+, uv, Codex with its CLI, and loopMIDI. The MIDI transport currently uses Windows WinMM; macOS and Linux are unsupported.
Clone the repository and open PowerShell in it:
git clone https://github.com/Radishoux/fl-codex.git
cd fl-codexInstall Python dependencies from this directory:
uv sync --lockedInstall our extension in FL's user-data folder:
uv run --locked python install.pyCustom location:
uv run --locked python install.py --user-data 'D:\Music\FL Studio'. The installer detects Windows' Documents folder, including OneDrive redirection. It copies only our controller and pairing configuration.In loopMIDI, create a dedicated virtual port named exactly
FL Codex. The relay looks up this name. Keep loopMIDI running: the virtual port exists only while it runs. No MIDI notes are sent by this bridge.In FL Studio, press F10 > MIDI, refresh the device list if needed, select the
FL Codexinput, enable it, and choose FL Codex Bridge under Controller type. Set its input Port to0. SelectFL Codexin the Output list and set its Port to the same0; leave Send master sync off. Use another matching number if0belongs to another device. Check View > Script output forFL Codex Bridge ready via MIDI SysEx; output assigned: True. If the new controller type is absent, refresh/reopen MIDI settings or restart FL after saving your own work. The installer never closes FL.Verify the live connection:
uv run --locked python bridge_client.py statusThe client starts the local MIDI relay automatically when needed. Keep loopMIDI running. Startup errors go to
.local/relay.log. To run the relay visibly for diagnosis:uv run --locked python relay.py(only one relay can own port 32123).Register the MCP server with Codex (one-time, from this directory):
$flCodexRoot = (Get-Location).Path codex mcp add fl-studio -- "$flCodexRoot\.venv\Scripts\python.exe" "$flCodexRoot\server.py"Reload Codex's MCP connections or open a new chat if the new tools are not available in the current chat. The CLI remains usable immediately.
Use
Name mixer tracks clearly, for example Guitar, Lead vocal, and Drums.
Select the target track or include its name in the instruction:
"List the effects on Guitar and their wet/mix parameters."
"Increase the guitar reverb wet amount slightly."
"Add a little drive using the distortion effect already on Guitar."
"Undo your last knob change."
Codex first reads the actual plugin and parameter names. Writes use a fresh handle and refuse to overwrite a knob that changed after inspection. Small requests default to a maximum normalized movement of 0.1; this is not a dB or percentage-of-perceived-loudness scale. Changes are refused while recording.
No manual MIDI CC assignment is needed for exposed plugin parameters. MIDI SysEx carries commands and replies; the FL script calls FL's parameter API. The virtual input is reserved for this bridge and consumes musical MIDI messages.
Verify / develop
uv run --locked python -m unittest discover -s tests -v
uv run --locked python scripts/check_mcp.py
uv run --locked python scripts/list_midi.pycheck_mcp.py regenerates tool_manifest.json from the real server. Tests bind
localhost sockets; a sandbox that prohibits loopback needs host permission.
The live acceptance procedure and implementation details are in docs/ARCHITECTURE.md.
See CONTRIBUTING.md for development and compatibility reports.
License
MIT. FL Studio, loopMIDI and other dependencies remain under their respective licenses and are not included in this repository. This is an independent project, not an official Image-Line or OpenAI product.
Available Tools
6 toolsget_fl_parametersBRead-only
Read parameter names, normalized values, display units and short-lived edit handles. Follow next_start.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | ||
| slot | No | Effect slot 0-9, instrument -1 | |
| index | Yes | Zero-based mixer or global channel index | |
| limit | No | Maximum parameters per page | |
| start | No | First parameter index |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/non-destructive/closed-world, and the description adds genuinely new context: the payload includes normalized values and display units, and the edit handles are 'short-lived' — a real constraint an agent must act on. It also signals pagination via next_start. It stops short of saying what the handles are for or what happens when they expire.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, and the return-payload summary is front-loaded. 'Follow next_start' is terse to the point of ambiguity, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining returns and does list the four payload elements, plus paging. However, it never explains how kind/slot/index combine to select a target, nor what an edit handle is used for downstream — meaningful gaps for a 5-parameter tool with required addressing fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80% — slot, index, limit and start are all documented in-schema, and kind is a self-explanatory two-value enum. The description adds nothing about parameter meaning; 'Follow next_start' refers to a pagination token that is not even a request parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A specific verb ('Read') plus the resource ('parameters') and an enumeration of what comes back: names, normalized values, display units, edit handles. It is clearly the read counterpart to set_fl_parameter, though it never names that sibling or otherwise differentiates itself explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this instead of set_fl_parameter or the list_* tools, and no prerequisites (e.g., needing a track/slot selected first). 'Follow next_start' hints at pagination handling but is the only usage-shaped guidance offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fl_statusARead-only
Check the live FL bridge, version, current selection, recording state and capabilities.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered structurally. The description contributes beyond that by enumerating what live state is surfaced (bridge, version, selection, recording state, capabilities), which tells the agent this is a cheap non-mutating probe. It does not say what happens when the bridge is down, so it is not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler, and the most important noun ("live FL bridge") leads. Nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description carries the burden of describing returns and it does so by listing the state facets. The only real gap is error/disconnected behavior, which matters for a tool whose whole purpose is checking a live bridge.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters and the schema is empty, so there is nothing for the description to disambiguate. Baseline 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ("Check") and names the resource plus the exact facets returned: bridge liveness, version, current selection, recording state, and capabilities. That is far more informative than the name alone. It stops short of naming a sibling it displaces, which keeps it out of the top band.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No sentence tells the agent when to call this versus list_fl_tracks, get_fl_parameters, or the mutation tools. A reader can infer it is a diagnostic/liveness probe, but the description never states prerequisites (e.g. call before other FL tools) or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_fl_pluginsARead-only
Discover loaded effects on a mixer track, or the instrument at a global channel index.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | ||
| index | Yes | Zero-based mixer or global channel index |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered structurally. The description confirms discovery/read behavior and clarifies the index domain, but it does not add much beyond that about errors, empty results, or other runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence that states the two operating modes without waste. Every clause contributes to selecting the right kind and index context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with safety annotations and a mostly self-explanatory schema, the description is sufficiently complete to support correct invocation. It could still say more about the returned shape or whether missing/out-of-range indexes produce errors, but those are minor gaps rather than blockers.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 50% schema description coverage, the description usefully clarifies that "kind=effect" applies to a mixer track index while "kind=instrument" applies to a global channel index. That mapping is important because the schema's index description alone is ambiguous across the two kinds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ("Discover") and resource ("loaded effects" / "instrument") and distinguishes the two modes by mixer track versus global channel index. It is clear, but it does not explicitly differentiate itself from siblings such as get_fl_parameters or list_fl_tracks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: to discover effects on a mixer track or an instrument at a global channel index. It does not state when not to use it or name alternatives, so it falls short of full usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_fl_tracksARead-only
List track names and indices; channel results also show mixer routing. Follow next_start.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | mixer | |
| limit | No | Maximum tracks to read | |
| start | No | First index in this page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely new behavioral context beyond the schema: that results are paginated via a next_start cursor (a return value not present in the input schema) and that output shape varies by kind.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the primary behavior front-loaded and no wasted words. "Follow next_start" is terse to the point of being slightly cryptic, since nothing explains that next_start is a returned cursor, but the density is appropriate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must carry return-value semantics, and it only partially does: names/indices, routing for channels, and a next_start cursor. It omits what the mixer kind returns, how the two kinds differ, and what happens when next_start is absent (last page).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67% — limit and start are already documented in the schema. The description adds partial meaning for the undescribed 'kind' enum by explaining what channel results contain, but never contrasts mixer vs channel or states what the default mixer mode returns. Baseline 3 fits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List track names and indices") and adds a conditional output distinction (channel results include mixer routing). It is clearly the only track-listing tool among siblings like list_fl_plugins and get_fl_parameters, though it never names the sibling it differs from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: "channel results also show mixer routing" hints that kind=channel is the choice when routing matters, but there is no explicit when-to-use/when-not statement or named alternative. An agent must infer which of mixer vs channel it wants.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_fl_parameterA
Change one freshly inspected knob and return actual readback. Refuses stale values and recording; stores bridge undo.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | Requested normalized value, not a physical unit | |
| handle | Yes | Fresh handle from get_fl_parameters | |
| max_delta | No | Largest intentional normalized move from the inspected value |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (not read-only, not destructive), and the description adds real value beyond them: the call returns actual hardware readback, it rejects stale handles and refuses while recording, and it pushes an undo entry so the change is reversible. It does not say how failures surface (error vs. silent no-op).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, mutation verb front-loaded, no filler. The telegraphic style ("stores bridge undo") trades a little clarity for density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating tool with no output schema, the description leaves the return value ("actual readback") undefined and does not say what happens on a max_delta violation or an out-of-band value. The preconditions it does cover are the ones that matter most, so it is adequate rather than complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each parameter already carries a description, so the schema does the heavy lifting. The description reinforces that handle must come from a live get_fl_parameters call but says nothing about value normalization or max_delta beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Change one ... knob and return actual readback" gives a specific verb plus a single-resource scope, which distinguishes it from get_fl_parameters (read) and undo_fl_change (revert). The jargon "knob" and "bridge undo" slightly obscure the object being changed, keeping it out of 5 territory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Freshly inspected" makes the prerequisite explicit: you must call get_fl_parameters first, and the "Refuses ... recording" clause tells the agent a context where it will not work. It never names an alternative sibling or says when to prefer undo_fl_change, so it stops short of explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
undo_fl_changeA
Restore the latest bridge knob change, provided the plugin and value still match. Does not invoke FL's global undo.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as non-read-only, non-destructive, and closed-world, and the description adds meaningful behavior: it restores only the latest matching bridge knob change and does not trigger global undo. It omits what happens when the plugin/value precondition is not met, leaving one behavioral gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the action and its precondition, and contains no redundant restatement of annotations or schema. Every sentence contributes useful selection or invocation context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter undo operation with annotations and no output schema, the description supplies enough scope, precondition, and exclusion context to call it correctly. The main remaining gap is failure behavior when the plugin/value precondition does not hold.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool defines zero parameters, so the schema carries no parameter-documentation burden. The description's mention of plugin and value matching refers to internal state conditions rather than inputs, which is a useful distinction.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action, 'Restore', and a specific resource, 'latest bridge knob change', while distinguishing it from FL's global undo. It does not explicitly differentiate from sibling tools such as set_fl_parameter, so sibling routing is only partially supported.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear usage condition: the plugin and value must still match. It also includes an exclusion by saying it does not invoke FL's global undo, but it does not name the alternative tool to use when the precondition fails or a broader undo is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
get_fl_parameters - First observed
get_fl_status - First observed
list_fl_plugins - First observed
list_fl_tracks - First observed
set_fl_parameter - First observed
undo_fl_change
TDQS
Scored across 6 tools
Each tool targets a distinct resource and action: status inspection, track listing, plugin listing, parameter reading, parameter writing, and undo. The boundary between inspecting a plugin and reading its parameters is clear from the descriptions.
All tool names follow a consistent snake_case verb_fl_noun pattern. The verbs are used predictably: get for reads, list for collections, set for mutation, and undo for reversal.
Six tools are well-scoped for an FL Studio bridge focused on safely inspecting and editing parameters. Each tool has a clear role and no obvious redundancy.
The parameter-editing lifecycle is covered: check status, discover tracks and plugins, read parameters, set a parameter, and undo a change. Minor gaps exist around broader FL Studio control such as transport actions, plugin loading, or redo.
Maintenance
Related MCP Connectors
Control Unreal Engine to browse assets, import content, and manage levels and sequences. Automate…
Use your Mac, Windows or Linux computer from ChatGPT, Claude or Codex: files, commands, documents.
Connect your AI assistant to Blender for 3D modeling, Geometry Nodes, materials, lighting, animation, rendering and export. Inspect real scenes and viewport images, refine the result and restore checkpoints. OAuth connects your chat to Blender Bridge Desktop on an online Windows 10/11 x64 computer running Blender 4.2+. The chat can run on another device. Requires an active Blender Bridge account; 7-day trial available. AI model access is separate.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to control FL Studio through MIDI communication, providing transport control, mixer adjustments, channel rack manipulation, plugin parameter automation, and piano roll note editing capabilities.262MIT
- 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
- AlicenseNot gradedqualityDmaintenanceBridges AI assistants with Ableton Live, enabling real-time control, offline project analysis, version tracking, and rack/preset parsing for music production workflows.MIT