kuruitsugizaki
This MCP server lets a model compose FL Studio music end-to-end — reading, writing and rendering .flp projects, and driving a live FL Studio — on Windows.
Configure & install the harness:
configdetects/sets machine paths (FL, loopMIDI, presets);fl_installwrites FL's controller script and wires a loopMIDI port;fl_probechecks the live link and its API version.Read projects:
project_readturns any.flpinto JSON (summary,compactrows, or byte-exactfull), with filters for patterns/arrangements and unused material — no FL needed.Write music:
project_writebuilds.flpfiles from compact JSON — notes, patterns, clips/arrangement, instruments (plugins by name, presets, or channels copied from saved projects), audio samples, and can open and play them in FL.Shape the mix: mixer volume/faders, routing and sidechain sends, effect slots (copied from FL-saved projects or by plugin name), plus automation clips for tempo, pitch, mixer, effect and channel parameters.
Discover sounds:
pluginslists installed instruments/effects and library instances;presetslists presets loadable by name per plugin;paramsgives automatable parameter indices and value scales.Hear the result:
fl_renderrenders to wav/mp3 via FL's command line plus spectrograms and stereo stats;fl_transportplays/stops the open project.Go live in FL:
fl_callinvokes one scripting-API function;fl_execruns arbitrary Python inside FL's embedded interpreter for multi-step reads/changes.Learn a style:
profileanalyzes a folder of someone's.flpprojects into markdown/JSON profiles with role pointers and master chain, for writing in their style.
kuruitsugizaki
An MCP server that lets a model read and write FL Studio projects and drive a running FL Studio, so it can write music. FL Studio is the first integration; the harness is meant to reach more software later.
The model does not listen. A render comes back as numbers and pictures (spectrograms, loudness, stereo width), and the person listens and decides.
Factory Seance, two minutes of glitchy witch house and breakcore, was written start to finish by Claude Opus 5.5 through this harness, in about 35 minutes: every note, drum hit, sound choice, mixer route and automation clip, from FL's factory sounds only. Nobody edited it; the person who asked for it listened afterwards and kept it as it was. Listen: examples/seance.mp3, the clip with sound: examples/demo.mp4, how it was made: examples/seance.md.
https://github.com/user-attachments/assets/8ee80e6e-cf6b-459d-bbe1-a83a50da325c
Windows only. To install it, follow INSTALL.md. Everything past setup and the tools (how to write a piece, the file format, traps, decisions) is under docs/, starting at docs/INDEX.md.
Requirements
Windows, FL Studio 2025. Built and measured on FL 25.1.6, scripting API 38.
loopMIDI with at least one port. FL loads the controller script only when its MIDI input port exists.
Python 3.12 or newer and
uv.ffmpegandffprobeon PATH, for the analysis scripts.Serum 2 to use the Serum 2 channel of the template. FLEX ships with FL.
Related MCP server: FL Studio MCP Server
Setup
The short way: close FL and double-click setup.bat. It installs what is missing (uv, loopMIDI, optionally ffmpeg), builds the environment, installs FL's controller script, makes the MIDI port and FL's MIDI setting, adds the server to the Claude desktop app, and ends with a check that FL answers. INSTALL.md lists every step and where it lands.
By hand, the same in four moves (INSTALL.md, By hand, has the detail):
uv syncRegister the server with the MCP client, with the path to this folder:
"kuruitsugizaki": { "command": "<this folder>\\.venv\\Scripts\\kuruitsugizaki.exe" }Then, in a chat with the model, FL closed:
It calls
config. On a standard install every path is found by itself (FL underProgram Files\Image-Line, the rest under your Documents folder) and shows asdetected; for anything not found it asks you where it is and sets it; it does not guess. The keys are inkuruitsugizaki.example.json; what you set is stored inkuruitsugizaki.jsonhere, which git ignores.It calls
fl_install, which writes the controller script into FL'sSettings\Hardwarefolder with this folder's bridge path filled in, adds a loopMIDI port namedkuruitsugizakiand assigns the script to it in FL's MIDI settings. Both of those live in the registry, and FL overwrites its own when it closes, which is why FL has to be closed.Only when
fl_installanswers that it could not make the MIDI setting: in FL, Options, MIDI settings, select a loopMIDI input port, controller type kuruitsugizaki, and restart FL once.
Script output in FL shows kuruitsugizaki {'api': 38, ...} on load. .venv\Scripts\python scripts\doctor.py prints one line per requirement, any time.
The server starts loopMIDI and FL itself when a live tool finds them closed.
Layout
file | what |
| the MCP server: tools, and the live link to FL |
| the machine paths, read from |
| the one-step install ( |
| for MCP directories' automated checks: runs the server on Linux, where the file tools work and the live link to FL answers that it needs Windows |
|
|
| the loopMIDI port and FL's MIDI input setting, both in the registry: reads them, and makes them when no input has the script |
| FL controller script; |
|
|
|
|
| compact and summary views, compact -> full |
|
|
| what CI runs, no FL needed: templates round-trip, a project from shipped parts builds and reads back, profile, the server's tool list; on Windows with FL also every example |
| project JSON -> |
| automation points (event 234) and targets (event 227) |
| mixer fader and main volume records in event 225 |
| mixer effect blocks: read one from any FL-saved project, place it in a track's slot |
| puts a preset into a plugin channel's state: |
| each synth's preset format, and |
|
|
|
|
| render -> PNG: semitone piano-roll spectrogram, chroma, 20 Hz-20 kHz spectrogram, RMS/peak, L/R correlation, ghost % over time with wash stretches ( |
| the wash check |
| integrated and momentary LUFS, LRA, true peak, RMS; |
| stereo density heatmaps per moment and band, |
| A/B of several renders at several zooms around each file's loudest second |
| hit onsets of a WAV, for chopping loops |
| cuts time ranges of a file into their own WAVs with short fades, optionally reversed |
| vocal -> syllables with a median pitch each |
|
|
| per-instrument note overview of a project |
| sent through |
| Serum 2 host-parameter mapping (parked) |
| Sylenth1's 244 parameter names in blob order |
| the template new projects are built from |
| a library of FL's own effects to copy from |
| seven small documents, one per part of the format (instruments, effects, routing and sidechain, global, mixer and instrument automation), and a full two-minute piece with its script, notes and render; |
| parameter maps, one TSV per plugin: 27 of FL's own and 22 VST3s, listed in |
Tools
tool | does |
| no arguments: every path key, its value or the path detected for it, and whether it exists; with |
| installs the controller script into FL's Hardware folder with the bridge path written in and, with FL closed and unless an input in FL already has the script, adds a loopMIDI port named |
|
|
| JSON (compact or full) -> |
| a table of the |
| saves FL's open project, then runs |
| play / stop, song / pattern mode |
| every plugin FL has installed, and every instance in the optional library project (see Plugins by name): name, instrument or effect, vendor, format, source, how many presets load by name, whether it has a parameter map |
| a library plugin's preset ids, filtered by words; the id goes into |
| a library plugin's parameters from |
| raw access to FL's Python API inside the running FL; |
project_read, project_write, profile, plugins, presets and params reload the codec modules on every call; a change to server.py, flex.py or diva.py needs an MCP restart, and a new tool reaches a client only in a session started after it.
The template
projects/init/init.flp, saved by FL: a Sampler, Serum 2, FLEX, one audio channel and one automation clip; master plus inserts 1-17, no effects. Route to inserts 1-16: insert 17 takes no fader on this mixer. A plugin instrument is copied from the template channel of that plugin, so with this template plugin takes serum2 or flex. The preset loaders also handle Vital, Diva and Sylenth1: to use them, save a template of your own in FL holding those plugins and set template to it, or take a channel from any project with state: {from, channel}. Template plugins are matched by name: Serum2, FLEX, Vital, Sylenth1, Diva(x64).
Effects
The writer cannot make an effect; it copies one, with its settings, from a project FL saved. projects/init/fx.flp holds FL's own:
from insert/slot | effect |
1/0 | Fruity Parametric EQ 2, saved with a band set (a high shelf at -18 dB); move or zero its bands before relying on it |
2/0 | Fruity Limiter |
3/0 | Fruity Limiter in compressor mode, set up for sidechain ducking |
4/0 | Fruity Reeverb 2 |
5/0 | Fruity Multiband Compressor |
6/0 | Soundgoodizer |
7/0 | Gross Beat |
Soundgoodizer and Gross Beat load only in an FL edition that includes them. Any other installed effect goes in by name (Plugins by name).
Plugins by name
Every plugin FL has installed can go into a project by name, with nothing to prepare: FL's plugin manager keeps one entry per plugin in its Plugin database (Documents\Image-Line\FL Studio\Presets\Plugin database, config key plugin_db, found by itself), and the writer builds the plugin from it on the template's blocks, fresh, as dragging it in from FL's browser does. plugins lists them; project_write takes an instrument as {"kind": "plugin", "plugin": "<name>", "preset": "<id>"} and an effect as mixer.effects: [{"track": t, "slot": s, "plugin": "<name>", "preset": "<id>"}]. A plugin installed in several formats is one name; add "format": "vst3" (or native, clap, vst) to pick one. A plugin FL has not scanned is not listed: run FL's plugin manager first.
Optionally, one project FL saved can hold tuned instances you want reused as they are, each instrument on its own channel, each effect in a mixer slot; set its path as config key library. A library instance wins over a fresh one of the same name.
Presets, listed by presets:
.fstfiles, from FL's factory and user Plugin presets folders (config keysfl_presets,fl_user_presets, found by themselves). FL writes one for any plugin from its plugin menu, VSTs included (a wrapped VST's go intoFruity Wrapper - <name>), so saving a sound there makes it usable by name.Vendor preset files for JUCE plugins (an XML preset) and Cableguys ones (
#zip#), from the folders config keyvst_presetsnames per plugin; a JUCE plugin needs no saved instance for this:{"<plugin>": {"ext": ".vpreset", "dirs": {"": "<factory folder>", "user": "<user folder>"}}}.
Parameter maps: open a copy of the library in FL (the sweep leaves every knob at 1) and send the text of scripts/params_fl.py through fl_exec once. Then _kz_dump('tmp/params/pass1_all.json'); for each v in 0, .25, .5, .75, 1, four separate fl_exec calls, _kz_sweep(v, 'set'), _kz_sweep(v, 'nudge'), _kz_sweep(v, 'back'), _kz_read('tmp/params/sweep_<v>.json') (a display read in the call that set it is stale); then python scripts/parammap.py writes docs/params/. Each function takes only and skip lists of plugin names as FL reports them (docs/params/INDEX.md, column as FL names it).
Project JSON, compact form
{
"format": "compact",
"base": "projects/init/init.flp",
"project": {"bpm": 175, "ppq": 96},
"instruments": [{"id": "lead", "kind": "plugin", "plugin": "serum2", "preset": "C:/presets/lead.SerumPreset", "mixer": 1},
{"id": "keys", "kind": "plugin", "plugin": "flex", "preset": "Hard 808s/808 Clean Fuzz", "mixer": 2},
{"id": "pad", "kind": "plugin", "state": {"from": "projects/my_song.flp", "channel": 3}, "mixer": 3}],
"samples": [{"id": "snare", "kind": "audio", "path": "C:/samples/snare.wav", "mixer": 8}],
"automation": [{"id": "fade", "kind": "automation", "target": {"mixer": 0, "param": "vol"}, "points": [[0, 0.8], [32, 0.0]]}],
"mixer": {"volume": {"1": 0.729, "7": 0.434}, "main_volume": 0.6625},
"note_cols": ["bar", "beat", "tick", "len", "key", "vel", "inst"],
"patterns": [{"id": "lead_a", "notes": [[1, 1, 4, 66, "A#4", 96, 0], [1, 2, 3, 18, "G#4", 80, 0]]}],
"clip_cols": ["track", "bar", "beat", "tick", "len", "src", "trim?"],
"arrangements": [{"name": "Arrangement", "clips": [[5, 17, 1, 0, 1536, "lead_a"], [4, 17, 3, 0, 31, "s0"], [20, 1, 1, 0, 27648, "a0"]]}]
}Time:
[bar, beat, tick], 1-based bar and beat, 96 ticks per beat, 4/4. Lengths in ticks. Exact integers; no grid is imposed.Keys: note names, MIDI 60 = C4 (FL's own UI calls MIDI 60 C5). Flats accepted.
Pointers: a note's
instis an index intoinstruments. A clip'ssrcis a pattern id,s<N>(sample N) ora<N>(automation N), so no instrument or pattern id may look likes1ora1.Patterns hold notes for any number of instruments. A clip's
lensets how much of a pattern plays.Instruments:
state: {from: file, channel: n}copies that channel whole, preset and routing included, from any FL-saved project, switched on even when it was muted there (muted: truekeeps it off;project_readreports a muted channel withmuted: true); or a templateplugin(see The template).presetloads a sound into it: a.SerumPreset,.vital,.h2por.fxppath, or<pack>/<preset>for FLEX.mixer: nroutes it. Serum 1.fxpare not supported.Sampler channels:
"kind": "sampler"with apathloads that file into a sampler, so notes pitch it (C4 = original pitch). A sampler plays its sample to the end whatever the note length; cut chops to their own files first (chop.py).Song mode: compact documents are saved in song mode so FL and its command-line render play the arrangement;
project.song_mode: falsesaves pattern mode.Samples:
path, orstateto copy one. An audio clip withouttrimplays the whole sample;trimis[start_ms, end_ms]into the sample. A path may start with%FLStudioFactoryData%, FL's own token for its install folder, so%FLStudioFactoryData%/Data/Patches/Packs/Drums/Kicks/808 Kick.wavfinds FL's factory kick on any machine.Project info:
projecttakestitle,author,genreandcomment, written into FL's project info (FL shows the title in its window), andproject_readreturns them.Automation:
pointsare[beat, value, tension?]in beats from the clip start. Targets:{"global": "tempo" | "main_pitch"},{"mixer": t, "param": "vol" | "pan" | "sep"}(insert 0 is the master: its fader is the overall level),{"mixer": t, "slot": s, "param": n}(effect parameter n),{"mixer": t, "slot": s, "rec": "0x1f00"}(the slot's mute) or"0x1f01"(its mix),{"channel": id, "param": n}(instrument parameter n) or{"channel": id, "param": "vol" | "pan" | "pitch" | "fcut" | "fres" | "mute"}. Values: tempo = (bpm - 60) / 120; main pitch 0.5 in tune, +-12 semitones; mixer volume 0.8 = 0 dB; pan 0 left, 0.5 centre, 1 right; sep 1 mono, 0 widest; channel pitch 0.5 in tune, +-48 semitones; channel volume 0.78 is FL's default.{"global": "main_vol"}is written but FL 2025 ignores it.examples/README.mdlists the scales measured so far (fcut, fres and mute are written but their scales were not measured).Mixer effects:
mixer.effects: [{"track": 0, "slot": 9, "from": {"file": "projects/init/fx.flp", "track": 2, "slot": 0}}]copies that effect with its settings into the given slot, replacing what was there.Mixer routes:
mixer.routes: [{"from": 11, "to": 10, "level": 0.0}]routes insert 11 to insert 10;level0 is a sidechain-only send, which is what a sidechained limiter or compressor listens to."on": falseremoves a route.Mixer volume:
mixer.volumemaps insert -> fader, 0.8 = 0 dB;main_volumeis FL's global main volume.base: the file whose globals, unmapped sections, arrangement track templates and mixer are kept. Building on one of your own projects keeps its mixer chains. Default: the
templatekey.
The compact form leaves out bytes that are not mapped. For editing an existing project without losing anything, use view="full".
Not written yet
Mixer pans and sends as static settings; a plugin FL's plugin manager has not scanned; pattern names; time signature; vendor preset files for VSTs whose state is neither JUCE XML nor #zip# (an .fst saved from FL is their route). See docs/FLP.md, Open.
License
MIT, see LICENSE. It covers this code and these docs, not FL Studio, the plugins or their presets.
Available Tools
13 toolsconfigAIdempotent
The paths on this machine the server needs (FL, loopMIDI, FL's Hardware folder, preset libraries), stored in kuruitsugizaki.json. Call it first in a new install, and whenever another tool answers that a key is not set. No arguments: every key with its value or the path detected for it, and whether that path exists. key alone: that key. key and value: set it. Never guess a path or search the disk for one: ask the user where it is, then set it.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | a key name, as the no-argument call lists them, e.g. 'fl_exe' | |
| value | No | the path to set for key; omit to read the key |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With destructiveHint=false, idempotentHint=true and readOnlyHint=false already declaring the safety profile, the description adds real context: the persistence target (kuruitsugizaki.json), the fact that a set mutates stored config, and the existence check returned for detected paths. It does not discuss permissions or failure behavior, but the core behavioral traits are disclosed.
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?
Purpose is front-loaded, followed by usage triggers, then the mode semantics and the prohibition. Every sentence is functional and none is padding, even though it is a single dense paragraph.
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 compensates by explaining the return shape of the no-argument call ('every key with its value or the path detected for it, and whether that path exists'). All three call modes, the storage file, and operational guidance are covered, so an agent has everything needed to invoke it correctly.
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 100% and each parameter is already documented, so the baseline is 3. The description's 'key alone / key and value' mapping reinforces the schema's semantics but adds little beyond what is already written in the property descriptions.
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 names the resource concretely — the machine-local paths the server needs (FL, loopMIDI, FL's Hardware folder, preset libraries) persisted in kuruitsugizaki.json — and then spells out the three operating modes (list-all, read-one, set-one). It is specific about what the tool does, though it never explicitly contrasts itself against siblings like fl_probe or fl_install; that differentiation is only implied.
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 explicit triggers ('call it first in a new install', 'whenever another tool answers that a key is not set') and an explicit prohibition with an alternative action ('Never guess a path or search the disk... ask the user where it is, then set it'). An agent knows both when to reach for it and what not to do instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fl_callADestructive
Call one function of FL's scripting API inside the running FL and return what it returns: {ok, value} or {ok: false, error}. For a single read or change, e.g. a parameter name or a mixer level of the open project. Use fl_exec for several calls or logic; use project_read and project_write for anything the .flp file holds, which need no FL. A setter changes the open project as an edit by hand would; nothing is saved. Launches FL if needed. Windows with FL Studio only.
| Name | Required | Description | Default |
|---|---|---|---|
| fn | Yes | module.function as FL's API names it, e.g. 'plugins.getParamName' | |
| args | No | its positional arguments, e.g. [0, 5, -1] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give destructiveHint=true/readOnlyHint=false, but the description adds the critical nuance that a setter edits the open project in memory 'as an edit by hand would; nothing is saved' — i.e. changes are transient and never written to the .flp. It also discloses that FL is launched if needed and that the tool is Windows/FL Studio only, which are real preconditions not present in the structured fields.
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?
Front-loads the action and return shape, then routes to alternatives, then discloses side-effect/launch/platform semantics. Every clause carries information; nothing is filler despite the fairly dense prose.
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 supplies the return contract itself ({ok, value} or {ok: false, error}). Combined with persistence semantics, launch behavior and platform limits, an agent has everything needed to invoke it safely.
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 100% and both parameters (fn, args) are documented with format examples in the schema, so the baseline is 3. The description adds no extra syntax or constraint detail beyond what the schema already states about 'module.function' and positional args.
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?
Specific verb+resource: 'Call one function of FL's scripting API inside the running FL and return what it returns', with the exact return shape ({ok, value} / {ok: false, error}). It distinguishes itself from siblings fl_exec, project_read and project_write by scope, so an agent can pick correctly without opening a schema.
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?
Explicit when-to-use ('For a single read or change, e.g. a parameter name or a mixer level') and explicit alternatives for other cases ('Use fl_exec for several calls or logic; use project_read and project_write for anything the .flp file holds, which need no FL'). No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fl_execADestructive
Run Python inside the running FL's embedded interpreter, where FL's modules (channels, mixer, plugins, transport, patterns, general ...) import. For live reads or changes that need several calls or logic; one call is simpler with fl_call. Returns {ok, value} with what the code assigns to result, or {ok: false, error} with the traceback. FL's sandbox refuses files, sockets and pipes. Changes act on the open project and are not saved. Launches FL if needed. Windows with FL Studio only.
| Name | Required | Description | Default |
|---|---|---|---|
| out | No | write the result as JSON to this path (relative to the repo) and return only its size, for large reads; also when `result` is {'__out__': path, 'data': value} | |
| code | Yes | Python source; assign the answer to `result` | |
| timeout | No | seconds to wait for FL's answer |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations: the sandbox refuses files/sockets/pipes, changes act only on the open project and are not saved, FL may be launched on demand, and the return shape is {ok, value} or {ok: false, error} with traceback. This is substantial extra context over the destructiveHint/openWorldHint flags.
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?
Four dense sentences, front-loaded with the core action and the fl_call disambiguation early. Slightly packed with environment caveats, but each sentence carries load.
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?
No output schema exists, yet the description explains both success and failure return shapes, the `result` contract, sandbox limits, persistence behavior and platform requirements. Nothing an agent needs to invoke this correctly is missing.
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 100%, so the schema already documents code, out and timeout. The description reinforces the `result` assignment convention and the __out__ path convention, but adds no syntax or format detail the schema lacks. 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?
Specific verb+resource: 'Run Python inside the running FL's embedded interpreter', with the module namespace (channels, mixer, plugins, transport, patterns) spelled out. It explicitly differentiates from the sibling fl_call ('one call is simpler with fl_call'), so an agent can route without opening either schema.
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?
Gives the selecting condition ('live reads or changes that need several calls or logic') and names the alternative (fl_call) for the simpler case. It also adds environment gates: Windows with FL Studio only, and it will launch FL if needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fl_installADestructiveIdempotent
Set up the live link to FL. Needed once per install, and again after this folder moves. Close FL first. It does two things: 1) writes FL's controller script into FL's Settings\Hardware folder (config key fl_hardware), with this folder's bridge path in it, replacing an older copy; 2) unless a MIDI input in FL already has the script, makes a loopMIDI port named kuruitsugizaki and assigns the script to it in FL's MIDI settings. Both live in the registry, which FL rewrites when it closes; if FL was open, the answer's midi entry says so and what to do by hand. Returns {ok, installed, bridge, changed, midi, next}. Then start FL and call fl_probe to see the script answer. Windows with FL Studio only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=false, but the description goes well beyond them: it names what is overwritten (an older copy of the controller script), where state lives (the registry, which FL rewrites on close), the failure mode when FL is open, and the exact return keys {ok, installed, bridge, changed, midi, next}. This is unusually rich disclosure for a mutation tool.
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?
Front-loaded with the essential trigger and prerequisite, and every sentence carries operational information. It is dense and somewhat run-on in the two enumerated steps, but nothing is padding, so it stays efficient without being maximal.
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 compensates by listing the return shape, and it covers prerequisites, platform scope, side effects, and the next step in the workflow. An agent has everything needed to decide whether and when to call it.
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, so per the rubric the baseline is 4. The description mentions a config key (fl_hardware) that the call writes, which is contextual rather than argument-related, and there is nothing further to document.
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 ('Set up the live link to FL') and then enumerates the two concrete actions it performs, so an agent knows exactly what happens without opening anything. It is clearly distinguishable from siblings like fl_probe, fl_call, and fl_exec, which are referenced as downstream steps rather than substitutes.
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?
Gives explicit trigger conditions ('needed once per install, and again after this folder moves'), a prerequisite ('Close FL first'), a platform constraint ('Windows with FL Studio only'), and the follow-up action ('start FL and call fl_probe'). It even names the conditional case where the MIDI port step is skipped.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fl_probeAIdempotent
Check the live link to FL: returns FL's scripting API version, its embedded Python version, FL's pid and the pipe handle it holds, or an error saying what is missing. Call it first when a live tool (fl_exec, fl_call, fl_transport, project_write with open) fails, and after fl_install. Launches loopMIDI and FL when they are not running (launched_fl_seconds says how long FL took). Reads nothing from the project. Windows with FL Studio only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
It goes well beyond the annotations by disclosing the real side effect (launches loopMIDI and FL when they are not running, with launched_fl_seconds reporting FL's startup time), which explains why readOnlyHint=false despite the tool not touching the project. It also promises a self-describing error rather than a silent failure. It stops short of covering timeouts, blocking duration, or what happens if a launch fails, which is why 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?
Front-loaded with the return values an agent needs to interpret the result, then the invocation triggers, then the side effects and platform caveats. Every clause carries information; nothing is redundant with the name or schema.
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, no-output-schema diagnostic whose behavior is environment-dependent, the description covers returns, side effects, triggers, and platform limits. Minor gaps remain around how long the call may block when it has to launch FL, or what the error states look like beyond 'an error saying what is missing'.
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, so per the rubric the baseline is 4. The description correctly implies a no-argument call and adds no confusing parameter talk.
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 names a specific operation (probe the live FL link) and enumerates exactly what it returns: FL's scripting API version, embedded Python version, pid, pipe handle, or a descriptive error. It is immediately distinguishable from siblings like fl_exec, fl_call, and fl_transport, which act on the link rather than diagnose it.
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 explicit triggers: call it first when a live tool (fl_exec, fl_call, fl_transport, project_write with open) fails, and after fl_install. It also names the platform precondition (Windows with FL Studio only) and states it reads nothing from the project, implicitly excluding it from data-retrieval workflows.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fl_renderADestructiveIdempotent
Render an .flp to audio: a .wav and .mp3 beside it (replacing earlier ones), then spectrogram and stereo statistics, so the result can be read as numbers and pictures. Call it after project_write to check a piece. FL renders from the command line, so the FL that is open is saved first (path itself is restored if that save overwrote it) and closed. Runs detached and returns at once with the log file to read for the results and file names; a 2-minute piece takes under a minute. Windows with FL Studio only.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | the key the piece is written in, e.g. 'F minor' or 'G#m'; the log then says how much pitch energy falls outside its scale | |
| path | Yes | the .flp to render | |
| reopen | No | open the project in FL again when done |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds critical operational context: it replaces earlier outputs, saves the open FL project first, restores the path if saving overwrote it, closes FL, runs detached, and returns a log file. It also gives timing expectations and platform limits.
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 front-loaded with the render outcome, then usage, side effects, return behavior, timing, and platform constraints. Every sentence carries necessary operational information with no filler.
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 complex, destructive, detached render tool with no output schema, the description explains what the call returns at once, how to read results via the log file, what files are produced, and key side effects. Nothing essential for correct invocation appears missing.
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 100%, so all three parameters are already documented in the input schema, including the key examples and the reopen default. The description does not add syntax or format details beyond what the schema provides, so the baseline of 3 is appropriate.
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: render an .flp to audio, producing .wav, .mp3, spectrogram, and stereo statistics. This distinguishes it from sibling tools like project_write, project_read, and fl_transport without requiring schema inspection.
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?
Explicitly says to call it after project_write to check a piece, and notes Windows with FL Studio only. It gives clear context and a prerequisite, though it does not name when-not to use it versus alternatives such as fl_transport.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fl_transportAIdempotent
Play or stop whatever project is open in the running FL, to hear it; it changes nothing in any file. action 'play' jumps to the start and plays (from the start, not from where it stopped; called while playing, it restarts from the start). action 'stop' stops playback. mode 'song' plays the arrangement, 'pattern' loops one pattern (pattern: its number, selected first); without mode FL keeps the one it has. Launches FL when it is not running, but then nothing is open: open a project with project_write(open=true), which can also start playback itself (play='song'). Returns {playing, mode}. To get audio out, use fl_render, which saves and closes FL instead. Windows with FL Studio only.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | 'song' or 'pattern'; omit to keep FL's | |
| action | Yes | 'play' or 'stop' | |
| pattern | No | in pattern mode, the pattern number to select first |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: play always jumps to the start rather than resuming, playback restarts if re-invoked, no file is modified, FL is launched if absent but with nothing open, and the return value is {playing, mode}. It also states the platform constraint (Windows with FL Studio only). This is consistent with destructiveHint=false and idempotentHint=true.
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 core action is front-loaded in the first clause, and no sentence is filler. It is a dense single paragraph with heavy parenthetical nesting, which slightly hurts scanability for an agent extracting the play/stop contract.
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?
There is no output schema, but the description supplies the return shape ({playing, mode}) plus the launch-state caveat and the cross-tool handoffs needed to actually get results. Nothing an agent needs to call this correctly is missing.
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%, so the baseline is 3, but the description adds real meaning: 'song' plays the arrangement, 'pattern' loops a single pattern which must be selected first, and omitting mode preserves FL's existing setting. The mode/pattern interaction is documented better here than in the schema alone.
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 pair (play/stop) over a specific resource (the project open in the running FL) and immediately scopes it: 'it changes nothing in any file.' It also distinguishes itself from siblings by name, pointing to fl_render for audio output and project_write for opening a project.
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?
Explicitly covers when each action applies, what 'play' does when already playing (restarts from start), how mode interacts with pattern, and what happens when FL is not running. It names the alternatives and the exact conditions that select them (project_write(open=true), play='song'; fl_render to save and close).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
paramsARead-onlyIdempotent
A plugin's automatable parameters, for writing automation: each one's index (the param of an automation target {channel: id, param: index} or {mixer: t, slot: s, param: index}), its name, and what its normalised value means where measured (FL's display at 0, .25, .5, .75 and 1, so a value can be picked for a wanted Hz, dB or %). Call it before automating a plugin or effect knob. It answers only for plugins with a parameter map (plugins shows which); for any other, read names live with fl_call('plugins.getParamName', ...). Not for choosing a sound: plugins lists what is installed, presets a plugin's presets. Reads files only; FL need not run.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | words that must all appear in the parameter name, case-insensitive, e.g. 'filter cutoff' | |
| plugin | Yes | the plugin's name as plugins lists it; a unique part of it works |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/false openWorld, so safety is covered. The description adds genuine behavior the annotations cannot: 'Reads files only; FL need not run' and the constraint that it only answers for plugins that have a parameter map. Return semantics for normalised values are also disclosed. No rate-limit or pagination notes, but those are likely N/A.
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?
Front-loaded with the core purpose in the first clause, then routing and caveats. Dense but nearly every clause carries information. The stacked parenthetical about automation-target shapes is the one spot that reads as cramped rather than crisp.
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?
No output schema exists, and the description compensates by explaining exactly what is returned (index, name, normalised value with FL's display at 0/.25/.5/.75/1 so a value can be chosen for a target Hz/dB/%). Combined with the routing guidance and the file-read-only note, an agent has everything needed to call and interpret it correctly.
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%, so both inputs (plugin, query) are fully documented in the schema and the description adds no input-format detail beyond it. The description's index/automation-target explanation ('{channel: id, param: index}') describes returned data and usage, not the input parameters, 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?
States a specific resource and scope: a plugin's automatable parameters, with each one's index, name, and normalised value meaning. It explicitly distinguishes itself from siblings 'plugins' (what is installed) and 'presets' (a plugin's presets), and names the fallback 'fl_call plugins.getParamName' for plugins lacking a parameter map.
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?
Gives explicit timing ('Call it before automating a plugin or effect knob'), explicit exclusions ('Not for choosing a sound'), and named alternatives ('plugins lists what is installed, presets a plugin's presets'). The condition under which the tool does NOT answer, and the workaround, are both stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pluginsARead-onlyIdempotent
List the plugins this machine has: every plugin in FL's plugin database, and every tuned instance in the optional library project. Call it to choose instruments and effects before project_write; then presets for a plugin's presets, params for its automatable parameters. Each row: name, kind (instrument or effect), vendor, format (native, vst3, clap, vst), source (fl or library), how many presets load by name, whether it has a parameter map. Any of them goes into project_write by name: an instrument as {kind: plugin, plugin: , preset?, format?}, an effect as mixer.effects [{track, slot, plugin: , preset?, format?}]; without a preset it arrives as if dragged in fresh from FL's browser, a library instance as saved. A plugin installed in several formats is one name (native, then vst3, clap, vst unless format is given). Reads files only; FL need not run.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | keep names containing this text, case-insensitive, e.g. 'serum'; omit for all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds real value beyond them: 'Reads files only; FL need not run' discloses that no host session is required, and it explains format-resolution precedence (native, then vst3, clap, vst) and what happens when no preset is given. It stops short of covering pagination or query behavior, but the read/write profile is fully clear.
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?
Front-loaded with the purpose, and the row-shape and project_write payload syntax are genuinely useful. It is dense, with several long run-on sentences that pack multiple facts per clause, but little 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 takes on the burden of describing returns and does so: it enumerates each row's fields (name, kind, vendor, format, source, preset count, parameter map) and explains how a listing entry maps into project_write arguments. An agent has everything needed to call it and use the result.
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?
There is a single optional query parameter whose schema description is 100% covered, so the schema already carries its meaning. The description adds no syntax or filtering detail beyond implying a general listing, so the baseline of 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?
States a specific verb and resource ('List the plugins this machine has') and scopes it precisely (FL plugin database plus tuned library instances). It is clearly distinguishable from siblings presets and params, which it names as separate concerns.
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?
Explicitly says when to call it ('to choose instruments and effects before project_write') and routes the agent onward to presets for a plugin's presets and params for automatable parameters. Nothing about selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
presetsARead-onlyIdempotent
List the presets that load by name for one plugin, as ids in catalog order; an id goes into project_write as an instrument's or effect's preset. Call it after plugins, when choosing a sound. Returns {plugin, kind, total, presets}; total counts every match even when limit cuts the list. A plugin name that matches nothing or several plugins returns {ok: false, error} naming the candidates. Reads files only; FL need not run.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | at most this many ids | |
| query | No | words that must all appear in the id, case-insensitive, any order, e.g. 'bass reese' | |
| plugin | Yes | the plugin's name as plugins lists it; a unique part of it works |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses the return shape ({plugin, kind, total, presets}), that total counts every match even when limit truncates the list, the ambiguous-match error behavior ({ok: false, error} naming candidates), and that it only reads files (FL need not run). This is rich context that annotations alone would not convey.
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 dense and front-loads purpose, then workflow, then return/error behavior. Every sentence carries information, though the single run-on style is slightly heavy; nothing is redundant.
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 fully compensates by describing the return shape, the total/limit relationship, and the error case. Combined with 100% parameter coverage, an agent has everything needed to call it correctly.
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% so the baseline is 3, but the description adds meaning: 'catalog order' ordering and the fact that total counts all matches even when limit cuts the list, which clarifies the limit parameter's semantics. The plugin matching behavior (unique part, ambiguous -> error) is also elaborated.
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 (List) and resource (presets) scoped to one plugin, and clarifies that ids are returned in catalog order. An agent can distinguish it from siblings like plugins and params without opening the schema.
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?
Explicit sequencing guidance: 'Call it after plugins, when choosing a sound.' It also routes the output forward, noting an id 'goes into project_write as an instrument's or effect's preset,' which tells the agent how this tool fits the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profileAIdempotent
List a person's projects from a folder of their .flp files; for one project's contents use project_read. Reads every .flp under the folder, subfolders included, and changes none of them; FL need not run; about 2 s for 80 projects. Returns a table of the projects: tempo, key, arrangement length in bars, so you know which to open and read in full with project_read; it decides nothing. Also written as profile.md and profile.json to tmp/profile//. Projects that fail to read are listed, not fatal; a folder with no .flp returns {ok: false, error}.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | Yes | the folder of .flp projects, absolute or relative to the repo |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations: recursion into subfolders, no modification of the .flp files, FL need not be running, ~2 s for 80 projects, the write of profile.md/profile.json to tmp/profile/<folder name>/, non-fatal read failures, and the {ok: false, error} shape on an empty folder. This is exactly the extra context annotations cannot carry, and readOnlyHint=false is consistent with the tmp file writes.
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?
Purpose and sibling routing are front-loaded, and every sentence carries information (timing, output, error behavior). Some clauses are densely stacked in a single run-on sentence, which costs a little readability.
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 one parameter, no output schema, and non-destructive annotations, the description still covers what is returned (tempo, key, arrangement length in bars), where artifacts are written, failure modes, and runtime. Nothing an agent needs to call this correctly is missing.
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 the folder parameter is already documented as absolute or repo-relative. The description still adds real semantics: recursion into subfolders and the fact that the folder name determines the output path under tmp/profile/.
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 a person's projects from a folder of their .flp files") and immediately distinguishes itself from the sibling that reads a single project's contents. An agent can tell profile apart from project_read without opening either schema.
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?
Routes the agent explicitly to project_read for single-project contents and frames profile as the survey step that decides which projects to open in full. It gives clear context for use but states no exclusions beyond that routing (e.g. what to do if the folder is huge or already profiled).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_readARead-onlyIdempotent
Read one FL Studio .flp file into JSON; FL need not run and the file is not changed. Use it to see what a project holds, to take parts from it, or to check what project_write wrote. For the style across many projects use profile; for the project open in FL right now, fl_exec. Views: 'summary' (start here: instruments, per-pattern stats, a per-track arrangement timeline, mixer effects); 'compact' (default: every note and clip as rows, the same shape project_write accepts; notes [bar, beat, tick, len_ticks, key, vel, instrument#], clips [track, bar, beat, tick, len_ticks, src, trim?] where src is a pattern id, s a sample, a an automation clip); 'full' (exact, round-trips byte for byte; large). Fails with the parser's error on a file that is not an .flp.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | the .flp file, absolute or relative to the repo | |
| view | No | 'compact', 'summary' or 'full' | compact |
| unused | No | also list patterns not placed in the playlist and parked clips | |
| patterns | No | only these pattern ids (compact and full) | |
| arrangements | No | only these arrangements, by name |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety baseline is covered. The description adds genuinely useful context beyond that: FL need not be running, the file is not changed, and the failure mode (parser error on a non-.flp). It stops short of describing pagination or cost of the 'large' full view in more detail, so a 4 rather than 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?
Front-loaded with purpose and the routing sentence before the detailed view breakdown, and every sentence carries information. The dense view/row-format sentence is long but earns its place; nothing is redundant boilerplate.
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?
Though there is no output schema, the description spells out the three view shapes and the exact field layout of the default return, plus error behavior — everything an agent needs to interpret results and call correctly is present for a 5-parameter read tool.
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%, so the baseline is 3, but the description substantially enriches meaning beyond the terse schema: it defines what each view returns ('summary' contents, 'compact' row shape, 'full' byte-for-byte round-trip) and the notes/clips row layout including the src encoding (pattern id, s<N> sample, a<N> automation). It never mentions the 'unused', 'patterns', or 'arrangements' parameters, leaving that to the schema.
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 ('Read one FL Studio .flp file into JSON') and immediately distinguishes itself from siblings by naming project_write (whose output it verifies), profile, and fl_exec. An agent can tell exactly what this does versus the other 12 tools without opening any schema.
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?
Gives explicit use cases ('see what a project holds, to take parts from it, or to check what project_write wrote') and routes alternatives by condition: profile for style across many projects, fl_exec for the project open in FL right now. This is textbook when-to-use/when-not coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_writeADestructiveIdempotent
Write a project document to an .flp file, replacing any file at path. This is how a piece gets made.
The document: the compact form project_read returns, or its full form. The field reference is README.md, 'Project JSON, compact form'; examples/README.md has a working document per feature. Read one before a first write.
Sounds:
an instrument is a plugin by name (see plugins) with an optional preset, or a channel copied from a saved project, state {from: file, channel: n};
an effect is mixer.effects {track, slot, plugin} or one copied, {track, slot, from: {file, track, slot}}.
Units that are easy to get wrong: 96 ticks per beat, 4/4; keys like 'D#4' with MIDI 60 = C4; mixer volume 0.8 = 0 dB; a tempo automation value is (bpm - 60) / 120.
Without open, FL need not run. With open or play, FL first saves the project it has open (so no dialog appears), then opens this one.
Returns the file read back (channels, notes per pattern, clips per arrangement) and the writer's warnings; read them.
| Name | Required | Description | Default |
|---|---|---|---|
| doc | Yes | the project document, compact or full | |
| open | No | open it in FL afterwards, launching FL if needed | |
| path | Yes | the .flp to write, absolute or relative to the repo; pieces go to projects/music/<piece>.flp | |
| play | No | 'song' or 'pattern': open it and start playback |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive=true and idempotent=true, but the description adds real behavioral context beyond them: the file at path is overwritten, FL may be launched, and with open/play FL first saves the currently-open project so no dialog appears. It also discloses that warnings are returned, which no annotation covers.
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?
Front-loaded with purpose and the overwrite warning, then organized into document, sounds, units, and runtime sections. It is long, but nearly every line carries actionable detail, so it stays efficient rather than padded.
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 present, the description compensates by stating the return shape (channels, notes per pattern, clips per arrangement, plus writer's warnings) and advising the agent to read them. Combined with the units and sound-definition guidance, an agent has everything needed to call it correctly.
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%, so the baseline is 3, but the description goes further by defining what 'doc' accepts (compact or full form), citing field references, and supplying hard domain units (96 ticks/beat, MIDI 60 = C4, 0.8 = 0 dB, tempo = (bpm-60)/120) that the schema does not encode.
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 ('Write a project document to an .flp file') plus the critical side effect ('replacing any file at path'), and clarifies it is the counterpart to project_read by describing the document it consumes. An agent can immediately distinguish it from project_read and the fl_* execution tools.
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?
Gives concrete context: read a working example before the first write, and explains the runtime condition ('Without open, FL need not run'). It does not explicitly name project_read or other sibling tools as alternatives, so it stops just short of full when-to-use/when-not coverage.
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.
1 tool update
v0.3.0- Changed
fl_render1 field changed- added
Input schema / properties / keyAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "the key the piece is written in, e.g. 'F minor' or 'G#m'; the log then says how much pitch energy falls outside its scale", + "title": "Key" +}
12 tool updates
v0.2.1- Changed
config2 fields changed- added
Input schema / properties / key / descriptionAdded value: +"a key name, as the no-argument call lists them, e.g. 'fl_exe'" - added
Input schema / properties / value / descriptionAdded value: +"the path to set for key; omit to read the key"
- Changed
fl_call2 fields changed- added
Input schema / properties / args / descriptionAdded value: +"its positional arguments, e.g. [0, 5, -1]" - added
Input schema / properties / fn / descriptionAdded value: +"module.function as FL's API names it, e.g. 'plugins.getParamName'"
- Changed
fl_exec3 fields changed- added
Input schema / properties / code / descriptionAdded value: +"Python source; assign the answer to `result`" - added
Input schema / properties / out / descriptionAdded value: +"write the result as JSON to this path (relative to the repo) and return only its size, for large reads; also when `result` is {'__out__': path, 'data': value}" - added
Input schema / properties / timeout / descriptionAdded value: +"seconds to wait for FL's answer"
- Changed
fl_render2 fields changed- added
Input schema / properties / path / descriptionAdded value: +"the .flp to render" - added
Input schema / properties / reopen / descriptionAdded value: +"open the project in FL again when done"
- Changed
fl_transport3 fields changed- added
Input schema / properties / action / descriptionAdded value: +"'play' or 'stop'" - added
Input schema / properties / mode / descriptionAdded value: +"'song' or 'pattern'; omit to keep FL's" - added
Input schema / properties / pattern / descriptionAdded value: +"in pattern mode, the pattern number to select first"
- Changed
params2 fields changed- added
Input schema / properties / plugin / descriptionAdded value: +"the plugin's name as plugins lists it; a unique part of it works" - added
Input schema / properties / query / descriptionAdded value: +"words that must all appear in the parameter name, case-insensitive, e.g. 'filter cutoff'"
- Changed
plugins1 field changed- added
Input schema / properties / query / descriptionAdded value: +"keep names containing this text, case-insensitive, e.g. 'serum'; omit for all"
- Changed
presets3 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"at most this many ids" - added
Input schema / properties / plugin / descriptionAdded value: +"the plugin's name as plugins lists it; a unique part of it works" - added
Input schema / properties / query / descriptionAdded value: +"words that must all appear in the id, case-insensitive, any order, e.g. 'bass reese'"
- Changed
profile1 field changed- added
Input schema / properties / folder / descriptionAdded value: +"the folder of .flp projects, absolute or relative to the repo"
- Changed
project_read5 fields changed- added
Input schema / properties / arrangements / descriptionAdded value: +"only these arrangements, by name" - added
Input schema / properties / path / descriptionAdded value: +"the .flp file, absolute or relative to the repo" - added
Input schema / properties / patterns / descriptionAdded value: +"only these pattern ids (compact and full)" - added
Input schema / properties / unused / descriptionAdded value: +"also list patterns not placed in the playlist and parked clips" - added
Input schema / properties / view / descriptionAdded value: +"'compact', 'summary' or 'full'"
- Changed
project_write4 fields changed- added
Input schema / properties / doc / descriptionAdded value: +"the project document, compact or full" - added
Input schema / properties / open / descriptionAdded value: +"open it in FL afterwards, launching FL if needed" - added
Input schema / properties / path / descriptionAdded value: +"the .flp to write, absolute or relative to the repo; pieces go to projects/music/<piece>.flp" - added
Input schema / properties / play / descriptionAdded value: +"'song' or 'pattern': open it and start playback"
- Removed
test
14 tool updates
v0.2.0- First observed
config - First observed
fl_call - First observed
fl_exec - First observed
fl_install - First observed
fl_probe - First observed
fl_render - First observed
fl_transport - First observed
params - First observed
plugins - First observed
presets - First observed
profile - First observed
project_read - First observed
project_write - First observed
test
TDQS
Scored across 13 tools
Most tools target distinct objects: plugins (installed plugins), presets (a plugin's presets), params (automatable parameters), project_read (one file), and profile (many files) are clearly separated. The main risk is fl_call vs fl_exec, both of which run code inside FL, but the descriptions explicitly frame fl_call as a single API call and fl_exec as multi-call logic, which mostly resolves it.
There is a recognizable scheme — fl_* for live-link tools (fl_render, fl_install, fl_probe, fl_call, fl_exec, fl_transport) and project_* for file tools (project_read, project_write) — but the remaining tools are bare nouns (plugins, presets, params, profile, config) with no verb, so the set mixes prefixed-verb and plain-noun conventions. It stays readable and grouped, but not a single predictable pattern.
13 tools is well within the healthy 3-15 range and each tool earns its place, covering distinct concerns (plugin discovery, presets, params, project I/O, rendering, profiling, config, install/probe, live API, transport). Nothing appears redundant or filler.
The surface covers the domain broadly: plugin/preset/param discovery, project read/write with sound and effect references, render to audio, multi-project profiling, config, live-link setup, live API access, and transport control. A few conveniences (e.g., dedicated sample/loop browsing or mixer/track editing outside project_write) are absent, but the core create-read-render-play lifecycle is closed.
Maintenance
Related MCP Connectors
Autonomous music production for AI agents with MIDI generation, QC and provenance.
Create and manage cinematic AI video renders through the Future Video Studio Agent API.
Generate full songs with vocals, instrumentals and sound effects from text. One server for Suno, Google Lyria, Mureka, MiniMax, ACE-Step, YuE and ElevenLabs. Your agent can quote the credit cost before generating, start a song, wait for it to finish and return download links. Sign in with OAuth; optional daily credit caps; retries never charge twice.
MCP server for Producer/Riffusion AI music generation
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.213MIT
- 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
- AlicenseBqualityBmaintenanceEnables AI agents to create, modify, and save LMMS music projects programmatically, including tracks, notes, mixer control, effects, and song settings.521MIT
- AlicenseCqualityBmaintenanceGives 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