kuruitsugizaki
Use kuruitsugizaki to configure a Windows FL Studio setup, read/write .flp projects, control and inspect live FL, render/analyze audio, and discover plugins, presets, parameters, samples, and project profiles.
Configure machine paths and install/repair FL’s controller script and loopMIDI link.
Read .flp files in compact, summary, full, or score views to inspect notes, clips, mixer, automation, and arrangements.
Write new or edited .flp projects from JSON, including instruments, plugins, presets, samples, patterns, automation, mixer effects/routes/volumes.
Open and play projects in FL, and control live playback with transport actions.
Render projects to WAV/MP3 and get spectrograms, loudness, stereo, onset, and report analysis.
Call FL’s live scripting API directly for reads or changes in the open project.
Discover installed plugins, presets, automatable parameters, sample folders, and profiles of existing projects.
Use FL factory sounds or user samples, with caching and optional measurement.
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.
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/d5ddff3b-1f48-4249-9a7c-0230aac6e610
Splinter Engine, made with 0.4.0.
https://github.com/user-attachments/assets/2984c857-38cc-4384-b51d-e807018261eb
Seven Lamps, made with 0.4.4.
https://github.com/user-attachments/assets/355de51f-cf49-410f-94c3-5f754773bfa7
Windows only for now. 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.
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 opens FL only for a project: project_write(open=true) and fl_render. Other live tools answer that FL is closed instead of starting it; fl_probe starts it to test the link and closes it again, and a first-time saved plugin state is made in FL and FL closed again (Plugins by name). An FL you started yourself is used when it is the only one open, and the result says so; the server closes only FLs it started, and with several FLs open and none of them its own it does nothing until you close the extra ones. Before acting on an FL you started, the server copies the project it has open to tmp/backups/<name>-<time>.flp, once per project per server run; the result says where the copy went and whether FL holds unsaved changes the copy lacks. FL gives no path, so the file is found by its name in the window title, and an untitled project is not copied. When FL crashes, the server reads the cause from Windows' Application log (faulting module, exception code) and returns it; an FL the harness started is closed with its crash handler and the Windows crash dialog, while a crashed FL of yours keeps its dialog. When FL shows a dialog and stops answering, the result names it and saves a picture of it to tmp/fl_dialogs/, and nothing more is sent to FL while it is up. A harness FL whose project FL reports changed is saved before it is closed, so closing never stops at "Save changes?".
Layout
file | what |
| the MCP server: tools, and the live link to FL |
| the machine paths, read from |
| the one-step install ( |
| undoes the setup: controller script, the MIDI port and FL's MIDI setting, the Claude entries, saved plugin states; settings move to |
| 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, summary and score 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 |
| the index behind |
| how every long list is cut: one item from each equal slice, first to last, at a random place in it, so each call differs |
| how setup, doctor and uninstall print: a rule per section, aligned rows with a coloured status |
| setup's path questions ( |
|
|
| 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 |
| the block effects by name are built on (config |
| 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 |
| the user's sample folders from config |
| saves and closes an FL the harness started, then runs |
| a finished render: the short report and the spectrogram picture together; says so while the render is still running |
| play / stop, song / pattern mode; needs a project open in FL |
| the VST3 and CLAP plugins FL has installed, and every instance in the optional library project (see Plugins by name); |
| a 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, FLEX, one audio channel and one automation clip; a mixer of inserts 1-125, no effects; a project routing past 125 is refused. Every plugin but FLEX loads by name; Serum 2, Vital, Diva and Sylenth1 take a preset ({"kind": "plugin", "plugin": "Vital", "preset": "<id>"}) into a state FL saved for them (Plugins by name). A template of your own holding them still works, matched by name: Serum2, FLEX, Vital, Sylenth1, Diva(x64).
Effects
An effect goes in by name: any effect FL has installed (Plugins by name). The first effect in projects/init/fx.flp is the block by-name effects are built on (config effect_template).
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. plugins leaves out what config hide_plugins names: by default FL's controllers, visualizers and notebooks, the VFX and FL Studio Mobile entries, Fruity Delay 2 and the first Parametric EQ, and every VST2 build. An entry is a name or * pattern, <format>:<name> for one format only, or category:<folder> for a category of FL's Plugin database. Setting the key replaces the default list. A hidden plugin cannot be written by name either.
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, found by default for Krush (
ProgramData\Tritik\Krush), Portal (ProgramData\Output\Portal\Presets), spiff (ProgramData\oeksound\spiff\Presets) and ShaperBox 3 (APPDATA\Cableguys\ShaperBox3, named by the preset name inside each file), and for any other plugin from the folders config keyvst_presetsnames:{"<plugin>": {"ext": ".vpreset", "dirs": {"": "<factory folder>", "user": "<user folder>"}}}. An entry there replaces a plugin's default. JUCE XML presets whose plugin keeps more in its state than the preset holds, as Krush and spiff do, are merged into that state; the rest replace it.Serum 2, Vital, Sylenth1, Diva and FLEX presets, from each plugin's own default folder plus any folders config
serum2_presets,vital_presets,sylenth1_presets(limited tosylenth1_folders) anddiva_presetsadd, and fromflex_packs. When a key has more than one folder, ids start with the folder's name. These presets, and vendor files fromvst_presets, load into a saved instance of the plugin. The first time one is needed,project_writeopens the plugin in FL, saves it, and keeps that state intmp/states/, which takes a few seconds once per plugin.NKS
.nksfpresets for any VST3 plugin, matched to it by the plugin id inside the file, from Native Instruments' User Content, the libraries in Public Documents, and confignks_presets; they need no saved instance.Presets built into a plugin, for a VST3 plugin with a parameter named
Program, such as TDR Kotelnikov: the harvest steps that parameter in FL and keeps each preset's state intmp/states/<plugin>.programs/, dropping exact duplicates such as empty user slots. A plugin with no preset files shows them afterpresets(plugin, harvest=True).
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 any plugin by name (Plugins by name).presetloads a sound into it: an id frompresets, or 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": 3, "slot": 0, "plugin": "<name>", "preset": "<id>"}]puts that effect in the given slot, replacing what was there;from: {file, track, slot}in place ofplugincopies one with its settings from a saved project.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
15 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. Needs FL open; it is not started for this.
| 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?
Goes beyond the annotations by disclosing the return shape ({ok, value} vs {ok: false, error}), that a setter mutates the open project 'as an edit by hand would', that nothing is saved, and that FL must already be running. The destructiveHint=true annotation is consistent with the setter caveat. It stops short of stating whether partial failures or invalid fn names are recoverable, but the added context is substantial.
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 core action and return contract, then layers usage routing and preconditions. Every sentence carries distinct information with no restatement of 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?
With no output schema, the description supplies the return contract itself, plus precondition (FL open), mutation semantics (edit-like, unsaved), and routing to alternatives. Nothing an agent needs before invoking a generic API-dispatch tool 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 'fn' (module.function) and 'args' (positional array) are already documented with examples in the schema. The description adds only an illustrative use case ('a parameter name or a mixer level') rather than deeper semantics, so 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 verb ('call one function of FL's scripting API') plus the exact return envelope, and positions it against siblings: fl_exec for multiple calls/logic, project_read and project_write for .flp contents. An agent can distinguish this from any other tool in the list 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?
Gives explicit selection criteria: use this for 'a single read or change', fl_exec for several calls or logic, project_read/project_write for anything the .flp holds. It also names a precondition — FL must be open and is not started for this — so the agent knows when the call will fail.
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. Needs FL open; it is not started for this.
| 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 beyond the annotations by disclosing the sandbox restrictions (no files, sockets, pipes), that changes act on the open project and are not saved, and the exact return shape for success and failure. The destructiveHint=true annotation is qualified rather than contradicted — mutations are real but discarded — which is valuable context. Minor gap: no mention of timeout behavior or long-running code.
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 core purpose and keeps every sentence load-bearing, but the later clauses are packed with multiple semicolon-joined facts in a single sentence, making it slightly denser than necessary.
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?
Despite no output schema, the description fully documents return values, the error/traceback form, sandbox limits, persistence semantics, and the FL-must-be-open prerequisite. Nothing an agent needs to invoke it 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 code, out, and timeout are already documented. The description reinforces the `result` assignment convention but adds no syntax, format, or edge-case detail about `out` or `timeout` beyond what the schema states, so 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?
Starts with a specific verb+resource ('Run Python inside the running FL's embedded interpreter') and enumerates the importable modules. It also names the sibling it differs from ('one call is simpler with fl_call'), so an agent can pick it out of a crowded toolset 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?
Gives an explicit selection rule: use this when work needs several calls or logic, otherwise prefer fl_call. It also states the prerequisite ('Needs FL open; it is not started for this'), which is exactly the when-not guidance an agent needs.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare mutation, destructiveness, and idempotency, and the description adds meaningful operational detail: it replaces an older controller script, conditionally creates and assigns a loopMIDI port, and explains registry-rewrite behavior. The note about FL being open and the returned midi guidance further reduces ambiguity.
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 main action and then uses a clear numbered structure for the two effects. Despite covering a complex install flow, every sentence carries useful operational information and there is 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 destructive, stateful setup tool with no output schema, the description is complete: it covers prerequisites, side effects, registry caveats, the returned fields, and the recommended next call. Nothing essential for correct invocation is omitted.
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 no parameters, so the baseline is 4. The description does not need to explain parameter semantics, and it correctly focuses on behavior and return value instead.
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 verb and resource: setting up the live link to FL. It immediately enumerates the two concrete setup actions, so the tool is distinguishable from fl_probe and other siblings.
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 usage conditions: needed once per install and again after the folder moves, with the prerequisite to close FL first. It also names the follow-up tool fl_probe, so the agent knows the next step in the workflow.
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. When FL is closed it starts it (and loopMIDI) to test the link and closes it again: launched_fl_seconds says how long FL took, closed_fl that it was closed. Reads nothing from the project.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations say readOnlyHint=false but not why; the description fills that gap by disclosing the actual side effect — when FL is closed it launches FL (and loopMIDI) to test the link, then closes it again. It also clarifies scope ("Reads nothing from the project") and names the response fields launched_fl_seconds and closed_fl, so the agent knows a slow call is expected behavior rather than a hang.
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 check-and-return contract, then the call conditions, then the side effect — a sensible order with no filler. The clause "launched_fl_seconds says how long FL took, closed_fl that it was closed" is elliptically compressed and takes a re-read, which keeps it just below a 5.
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, so the description carries the full burden of describing return values — and it does, listing the version fields, pid, pipe handle, error shape, and the two launch/close indicators. Combined with the failure-recovery guidance, an agent has everything needed to call it and interpret 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?
The tool takes no parameters and the schema is empty at 100% coverage, so there is nothing for the description to clarify. Baseline 4 applies; no parameter guidance is needed or missing.
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 ("Check the live link to FL") and enumerates exactly what it returns: scripting API version, embedded Python version, pid, pipe handle, or a descriptive error. It also names the sibling live tools (fl_exec, fl_call, fl_transport, project_write) so an agent can place it in the tool set 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 triggering conditions: call it first when a live tool fails, and after fl_install. This is a precise when-to-use rule tied to named siblings, not an implied one.
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 a spectrogram and a short report. Call it after project_write to check a piece. FL renders from the command line, so an FL the harness started is saved first and closed; an FL the user started is left alone and the render refused until they close it. Runs detached and returns at once; a 2-minute piece takes under a minute. Returns {ok, rendering, log, saved_open_project}. Then call render_report(path) until it stops saying the render is running, and make no live call (fl_exec, fl_call, fl_transport) before that: FL is closed while it renders.
| 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, and the description's 'replacing earlier ones' is consistent with that. It adds substantial useful context – detached execution, timing, harness-saved-and-closed behavior, refusal when user FL is open, and the return shape – which is meaningful beyond annotations. However, several of these (return shape, follow-up loop) are more procedural than behavioral-safety disclosure, so a 3 is appropriate rather than the top of the range.
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?
Dense and front-loaded: the core action and artifacts come first, prerequisites and caveats follow. A few sentences are lengthy (the FL closed-while-rendering note), but every sentence carries operational information. Slightly long, but 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?
Although there is no output schema, the description spells out the return object {ok, rendering, log, saved_open_project} and the follow-up protocol (poll render_report until it stops saying rendering). For a detached, stateful render tool, an agent has everything needed to call it correctly and handle the async 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?
Schema coverage is 100% and all three parameters are fully described in the schema (key, path, reopen), so the schema does the heavy lifting. The description does not add syntax or meaning beyond the schema for these parameters. 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 and resource (render an .flp to audio) plus the exact artifacts produced: .wav, .mp3 beside it, a spectrogram, and a short report. Clearly distinguishes itself from siblings by naming project_write, render_report, fl_exec, fl_call, and fl_transport with their relationship to this tool.
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 (after project_write to check a piece) and gives a negative constraint: make no live call (fl_exec, fl_call, fl_transport) before the render stops running. It also explains the refusal condition for a user-started FL instance, leaving no ambiguity about prerequisites.
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' plays from the start, also when called while playing. 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. Needs FL open with a project; it is not started for this: open one 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.
| 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?
Adds real context beyond the annotations: nothing is written to any file, FL is not launched, playback restarts from the beginning even when already playing, and the return value is {playing, mode}. Minor tension with idempotentHint=true since a repeated 'play' restarts playback, but the description discloses this rather than hiding it, so it informs the agent.
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 action and its effect on files, and every sentence carries information. It is dense and semicolon-heavy, bordering on run-on, which slightly slows parsing but does not waste words.
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 shape ({playing, mode}), the runtime prerequisite, the mode fallback behavior, and the handoff to fl_render for actual audio. 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%, yet the description still adds semantics the schema lacks: 'song' means arrangement, 'pattern' loops a single pattern, the pattern number is selected first, omitting mode preserves FL's current mode, and play always starts from the beginning. This is meaningful enrichment over bare enum-like strings.
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) and resource (the open project's transport in the running FL), and explicitly scopes it as non-file-changing. It also distinguishes itself from fl_render, which saves and closes FL, so an agent can separate it from the nearest sibling.
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 clear preconditions (FL must already be open with a project; use project_write(open=true) otherwise) and names the alternative for audio capture (fl_render). It does not state when *not* to use it in favor of fl_probe or fl_call, but the routing guidance it does give is strong.
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 |
|---|---|---|---|
| kind | No | 'instrument' or 'effect', for a name that is both; without it the instrument is taken | |
| 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 cover safety (readOnly, idempotent, non-destructive), and the description adds beyond them: it only answers for plugins with a parameter map (a real coverage limitation) and that it 'reads files only; FL need not run', telling the agent it works without a live session.
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 and output meaning, then routing and caveats. Dense but every sentence carries information; the long nested automation-target parenthetical is the only heavy patch.
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, so the description must explain returns — and it does: index usable as an automation target, name, and the normalised-value display at 0/.25/.5/.75/1 so a value can be chosen for a target Hz, dB or %. Nothing needed to call it 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 schema already documents 'kind' (instrument/effect disambiguation), 'query' (case-insensitive all-words match), and 'plugin' (name from plugins). The description adds little parameter-level detail beyond implying that names are matched against the plugin's list; baseline 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+resource: it returns a plugin's automatable parameters, each with its index, name, and what its normalised value means. It explicitly distinguishes itself from 'plugins' (lists what's installed), 'presets' (a plugin's presets), and fl_call('plugins.getParamName', ...) for plugins without 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 an explicit trigger ('Call it before automating a plugin or effect knob') and explicit non-uses ('Not for choosing a sound: plugins lists what is installed, presets a plugin's presets'), plus the fallback route for plugins lacking a parameter map.
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). By default it lists only VST3 and CLAP plugins; native=true adds FL's own. 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 | |
| native | No | true also lists FL's own (native) plugins |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a safe read-only operation, but the description adds substantial behavior: file-only reads, no running FL instance needed, default filtering behavior, format deduplication rules, and the exact row fields returned.
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?
Despite its length, the description is front-loaded with the core purpose and every sentence carries useful information about return fields, filtering, deduplication, or project_write integration. There is no redundant 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?
With no output schema, the description compensates by documenting the returned row fields and how names map into project_write. Combined with annotations and full schema coverage, an agent has enough context 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 description coverage is 100%, so the parameter meanings are fully documented in the schema. The description repeats the native behavior but adds no new semantics for query, making the baseline 3 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: list the plugins this machine has, covering both FL's plugin database and tuned library instances. It clearly distinguishes itself from siblings like presets and params while also explaining how results feed into project_write.
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 before project_write to choose instruments and effects, and directs the agent to presets or params for plugin subresources. It also explains the default VST3/CLAP-only listing and the native=true override.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
presetsAIdempotent
List the presets that load by name for one plugin; 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, and when there are more than limit the list is an even spread across the preset folders, each folder an equal share, not the first ones. A plugin name that matches nothing or several plugins returns {ok: false, error} naming the candidates. Reads files only and FL need not run, except with harvest, which opens the plugin in FL and adds its built-in presets to the catalog.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | 'instrument' or 'effect', for a name that is both (Serum2); without it the instrument is taken | |
| 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 | |
| harvest | No | first read the plugin's built-in presets from FL (opens it there once, about a second per preset); for a plugin whose presets live inside it, not in files |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the return shape, that total counts all matches, that limit produces an even spread per preset folder rather than a truncated prefix, the {ok:false, error} result for ambiguous/unknown plugin names, and that harvest opens the plugin in FL at ~1s per preset. This also explains why readOnlyHint=false despite the otherwise file-only read.
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 caller order come first, then return shape, then paging semantics, then failure mode, then the harvest caveat. Dense but every sentence carries information an agent would otherwise have to discover by error.
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 both the success payload keys and the error payload, states the FL-runtime caveat for harvest, and covers the ambiguous-plugin failure. Nothing needed 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; the description still adds value by explaining what the returned id is consumed by and how a plugin name that matches several plugins fails with named candidates. Parameter-level details (kind, query, limit) are left 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?
Specific verb + resource (list presets for one plugin) plus the downstream consumer ('an id goes into project_write as an instrument's or effect's preset'), which tells an agent exactly what the output is for. It also names the ordering dependency on the 'plugins' sibling, so it is clearly distinguishable from others in the set.
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?
'Call it after plugins, when choosing a sound' gives an explicit sequencing rule and trigger condition, and the harvest note says when the harvest variant applies (presets living inside the plugin, not on disk). No explicit when-not or comparison to the adjacent 'samples' sibling is given, which keeps it short of a 5.
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: tempo, key and arrangement length in bars, so you know which to open and read in full with 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. 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}. Without folder it reads config projects_folder; when that is not set, ask the user where their own projects are and pass that folder, which is then saved there, so later sessions do not ask again. When they have none, set projects_folder to 'none' with config, and profile then answers that.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | the folder of .flp projects, absolute or relative to the repo; omit to use config projects_folder |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond annotations: reads subfolders recursively, FL need not be running, ~2s for 80 projects, writes profile.md/profile.json to tmp/profile, failed reads are listed not fatal, and the {ok: false, error} shape for an empty folder. The readOnlyHint=false annotation is consistent (the tool writes report files while changing no .flp), and the description clarifies this distinction.
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 what it does and returns before the fallback logic, and every clause carries information. It is a dense, semicolon-heavy run-on paragraph, costing a little readability, 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 fully carries the return burden: it lists per-project fields, the error shape, the on-disk artifacts, and the config resolution behavior. Nothing an agent needs to call it 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, so the schema carries the base meaning. The description adds value beyond it by explaining the full default chain (config projects_folder, then ask-and-persist), which the schema only gestures at with 'omit to use config projects_folder'.
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+resource ('List a person's projects from a folder of their .flp files') and enumerates the returned fields (tempo, key, arrangement length in bars). It explicitly distinguishes itself from the sibling project_read ('which to open and read in full with project_read').
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 positions itself as the lightweight triage step before project_read, and gives detailed fallback guidance: omit folder to use config projects_folder, ask the user and save it when unset, and set projects_folder to 'none' when the user has none. When and when-not are both covered.
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, the parts sounding in each bar, 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, so narrow it with patterns or arrangements); 'score' (a bar range of the first arrangement as text, one row per step and one column per part, so how the parts line up can be read; bars [first, last]). Fails with the parser's error on a file that is not an .flp.
| Name | Required | Description | Default |
|---|---|---|---|
| bars | No | score only: [first, last] bar, at most 16; default the first 4 | |
| path | Yes | the .flp file, absolute or relative to the repo | |
| view | No | 'compact', 'summary', 'score' or 'full' | compact |
| unused | No | also list patterns not placed in the playlist and parked clips | |
| patterns | No | only these pattern ids (compact, full and score) | |
| 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, but the description goes well past them: it states the file is unchanged, warns that 'full' is large and should be narrowed with patterns or arrangements, and discloses the failure mode ('the parser's error on a file that is not an .flp').
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 action and the not-running/not-modified guarantees before any detail. It is long, and the view catalogue is dense, but nearly every clause carries decision-relevant information; only the inline tuple formats are slightly heavy for a description.
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 six parameters, no output schema, and four view modes, the description supplies exactly what is missing: the return shape per view, the default, the sizing caveat for 'full', and the error behavior. An agent can pick a view and call it correctly without opening anything else.
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 already documents bars, patterns and arrangements, so the schema carries the basics. The description still adds real value by explaining what each view returns and in what shape (note and clip row formats, per-bar sounding parts, score layout) and by naming 'compact' as default and 'summary' as the starting point.
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') plus two crucial scope facts: FL need not be running and the file is not modified. It explicitly distinguishes itself from siblings profile and fl_exec by naming what those cover instead.
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 three concrete use cases ('see what a project holds', 'take parts from it', 'check what project_write wrote') and names the alternatives with the condition that selects them: profile for style across many projects, fl_exec for the project open in FL right now. Nothing 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.
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. Mixer inserts run 1-125.
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 declare destructiveHint=true and idempotentHint=true, but the description adds genuine operational detail beyond them: the file at path is replaced, FL need not be running unless open/play is used, and FL first saves its currently open project before opening this one. The side-effect chain (launch FL, save existing project) is disclosed, which annotations alone do 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?
Front-loaded with purpose and the destruction semantics, then organized into scannable sections (sounds, units, behavior, returns). Dense but each block is functional; the units section is arguably long but directly prevents common errors.
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 tool with no output schema and nested input, the description covers return values ('the file read back... and the writer's warnings; read them'), input format and reference material, unit conventions, and open/play side effects. An agent has what it needs to construct a document and predict consequences.
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 baseline is 3, but the description meaningfully elaborates the complex nested doc parameter: compact vs full form, the 'sounds' shapes (instrument as plugin+preset, effect as mixer.effects or copied form). It also warns about easy-to-mistake units. This adds real value over the schema's terse 'compact or full' note.
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, replacing any file at path.' This makes clear it is the write counterpart to project_read, and the follow-up 'This is how a piece gets made' frames the outcome an agent produces.
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?
Given clear workflow context: 'Read one before a first write' points the agent to the README/example reference, and 'Without open, FL need not run' contrasts the open/play variants. It stops short of explicitly routing to sibling tools (e.g. project_read) by name, so 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
render_reportAIdempotent
Read what fl_render produced: the short report (length, peak, key, the number of parts sounding in each bar, and a flag only where something is found) and the spectrogram picture, as [text, image]. Call it after fl_render; it does not wait, and while the render is still going it says so: call again. With no render on record it answers to call fl_render first; a render that failed comes back as its log. Look at the picture before handing a piece over; the full analysis is in the .txt the report names. FL need not run. It writes into tmp/spectro/ only: a resized picture, and the spectrogram and its .txt again from the .wav when the log has no analysis.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | the path given to fl_render, or the .wav beside it; only its file name is used to find the render, so two pieces with the same name in different folders share one report |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses non-blocking behavior ("it does not wait... while the render is still going it says so: call again"), the failure path (a failed render returns its log), and concrete side effects ("writes into tmp/spectro/ only" — a resized picture plus regenerated spectrogram and .txt). These are consistent with readOnlyHint=false, idempotentHint=true and destructiveHint=false, and add real operational context.
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?
Information-dense but written as a semicolon-chained run-on with oblique phrasing ("it answers to call fl_render first"), which forces re-reading. The most important fact — that it reads rather than renders — is front-loaded, but the middle clauses bury the polling instruction and side-effect notes.
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?
Despite no output schema, the description covers the return shape ([text, image]), what the text contains, the in-progress case, the failure case, the no-prerequisite case, and the on-disk side effects. An agent has everything needed to call it correctly and interpret its 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?
Schema description coverage is 100% and the schema already explains that only the file name is used to locate the render, including the same-name collision caveat. The prose only echoes this indirectly ("the .wav beside it"), so it adds little meaning beyond the structured field — 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 verb and resource — read what fl_render produced — and enumerates the two return artifacts (short report text and spectrogram image) as [text, image]. It is explicitly positioned against the sibling fl_render that generates the output, so an agent can tell the producer from the reader 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 explicit ordering ("Call it after fl_render"), an alternative when the precondition is unmet ("With no render on record it answers to call fl_render first"), and downstream workflow guidance ("Look at the picture before handing a piece over"). It also states that FL need not be running, removing a common source of mis-invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
samplesAIdempotent
List samples for drums, one-shots, loops and breaks; a sample's path (its folder plus its name) goes into project_write as a sampler's or audio clip's path. Call it before choosing any sample, and take samples only from folders the user gave.
No arguments: the user's sample folders, each with its subfolders and how many audio files each holds. With query, the samples whose path matches; with folder, that folder's subfolders and files, and a query stays inside it. Returns {total, results: {folder: [[name, seconds]]}}; past limit the list is an even spread across folders.
When config sample_folders is not set it returns {ok: false, error}: ask the user where their samples are and set it with config (a folder or a JSON list), or 'none' when they have none, which makes FL's factory packs the source; the answer is kept.
Changes no sample file; FL need not run. It caches folder listings in tmp/samples/index/; measure also writes tmp/samples/.tsv.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | at most this many samples | |
| query | No | words that must all appear in the path below the sample folder, case-insensitive, any order, any depth, e.g. 'snare tight' | |
| folder | No | one folder to look into: absolute, below a sample folder, or %FLStudioFactoryData%/...; omit for all sample folders | |
| measure | No | also write the folder's own audio files' levels, width, onsets and centroid to tmp/samples/<folder>.tsv | |
| max_folders | No | at most this many folders in a folder listing, whole levels from the top | |
| max_seconds | No | keep samples at most this long, e.g. 1 for one-shots | |
| min_seconds | No | keep samples at least this long |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, and the description reconciles that by stating 'Changes no sample file' while disclosing the actual writes: folder-listing cache in tmp/samples/index/ and a TSV when measure is set. It also documents the failure shape {ok: false, error} and that FL need not be running — context the annotations cannot express. Return-record format and truncation behavior are covered too, leaving only minor gaps like cache invalidation timing.
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?
Core purpose and the project_write handoff are front-loaded, and the paragraph breaks map to distinct modes (default, filtered, error, side effects). It is denser than it needs to be in places — semicolon-chained clauses and the tmp/ path details could be tightened — but no sentence is pure 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 7-parameter, all-optional tool with no output schema, the description supplies the return shape ({total, results: {folder: [[name, seconds]]}}), the error shape, truncation policy, and side effects. An agent has everything needed to call it correctly on the first try.
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 schema baseline already carries per-parameter meaning. The description nonetheless adds non-obvious semantics the schema omits: that the no-argument form lists all sample folders with subfolder counts, that a query stays confined inside a supplied folder, and that past limit the results are an even spread across folders rather than a truncated head.
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?
Opens with a specific verb and resource ('List samples for drums, one-shots, loops and breaks') and immediately connects its output to a sibling ('a sample's path ... goes into project_write'). An agent can distinguish it from presets, plugins, and project_read 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?
Explicit sequencing ('Call it before choosing any sample'), an explicit constraint ('take samples only from folders the user gave'), and a documented recovery path when config sample_folders is unset (ask the user, then set it with config, or 'none' for factory packs). It names the alternative tool and the condition that selects it.
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.
5 tool updates
v0.4.5- Changed
params1 field changed- changed
Input schema / properties / query / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } +]
- Changed
plugins1 field changed- changed
Input schema / properties / query / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } +]
- Changed
presets1 field changed- changed
Input schema / properties / query / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } +]
- Changed
project_read3 fields changed- added
Input schema / properties / barsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "score only: [first, last] bar, at most 16; default the first 4", + "title": "Bars" +} - changed
Input schema / properties / patterns / descriptionPrevious value: -"only these pattern ids (compact and full)"New value: +"only these pattern ids (compact, full and score)" - changed
Input schema / properties / view / descriptionPrevious value: -"'compact', 'summary' or 'full'"New value: +"'compact', 'summary', 'score' or 'full'"
- Changed
samples2 fields changed- changed
Input schema / properties / max_folders / descriptionPrevious value: -"at most this many folders in a folder listing: whole levels from the top, the last level shared across its parents"New value: +"at most this many folders in a folder listing, whole levels from the top" - changed
Input schema / properties / query / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } +]
2 tool updates
v0.4.2- Changed
render_report1 field changed- changed
Input schema / properties / path / descriptionPrevious value: -"the .flp (or its .wav) that fl_render rendered"New value: +"the path given to fl_render, or the .wav beside it; only its file name is used to find the render, so two pieces with the same name in different folders share one report"
- Changed
samples4 fields changed- changed
Input schema / properties / folder / descriptionPrevious value: -"one folder to look into; omit for all sample folders"New value: +"one folder to look into: absolute, below a sample folder, or %FLStudioFactoryData%/...; omit for all sample folders" - changed
Input schema / properties / max_folders / descriptionPrevious value: -"at most this many folders in a folder listing"New value: +"at most this many folders in a folder listing: whole levels from the top, the last level shared across its parents" - changed
Input schema / properties / measure / descriptionPrevious value: -"also measure the folder's own audio files into tmp/samples/<folder>.tsv"New value: +"also write the folder's own audio files' levels, width, onsets and centroid to tmp/samples/<folder>.tsv" - changed
Input schema / properties / query / descriptionPrevious value: -"words that must all appear in the path, case-insensitive, any order, e.g. 'snare tight'"New value: +"words that must all appear in the path below the sample folder, case-insensitive, any order, any depth, e.g. 'snare tight'"
6 tool updates
v0.4.0- Changed
params1 field changed- added
Input schema / properties / kindAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "'instrument' or 'effect', for a name that is both; without it the instrument is taken", + "title": "Kind" +}
- Changed
plugins1 field changed- added
Input schema / properties / nativeAdded value: +{ + "default": false, + "description": "true also lists FL's own (native) plugins", + "title": "Native", + "type": "boolean" +}
- Changed
presets2 fields changed- added
Input schema / properties / harvestAdded value: +{ + "default": false, + "description": "first read the plugin's built-in presets from FL (opens it there once, about a second per preset); for a plugin whose presets live inside it, not in files", + "title": "Harvest", + "type": "boolean" +} - added
Input schema / properties / kindAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "'instrument' or 'effect', for a name that is both (Serum2); without it the instrument is taken", + "title": "Kind" +}
- Changed
profile5 fields changed- added
Input schema / properties / folder / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / folder / defaultAdded value: +null - changed
Input schema / properties / folder / descriptionPrevious value: -"the folder of .flp projects, absolute or relative to the repo"New value: +"the folder of .flp projects, absolute or relative to the repo; omit to use config projects_folder" - removed
Input schema / properties / folder / typeRemoved value: -"string" - removed
Input schema / requiredRemoved value: -[ - "folder" -]
- Added
render_report - Added
samples
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 15 tools
Each tool targets a distinct stage of the FL Studio workflow: setup/diagnostics, project file read/write, live scripting, transport, rendering, and metadata discovery. The only close pair is fl_call vs fl_exec, but the descriptions clearly separate single API calls from multi-call Python logic. Resource-specific tools like plugins, presets, params, samples, and profile are all clearly differentiated.
Names are consistently snake_case and use meaningful prefixes: fl_* for live/FL-facing operations and project_* for file operations, with bare nouns for catalog/config tools. There are minor deviations from a uniform verb_noun pattern, such as profile, samples, plugins, fl_probe, and fl_transport, but the grouping is still readable and predictable.
Fifteen tools is at the upper end of the ideal range but appropriate for a complex domain spanning setup, project file generation, live control, rendering, and asset discovery. Each tool has a clear role and does not appear redundant within the set.
The surface covers setup, diagnostics, project reading/writing, live API/Python access, transport, rendering, and plugin/sample/preset/parameter discovery comprehensively. Minor gaps remain around explicitly saving live edits and file-level operations such as delete/rename, though these are partly workable through project_write or fl_exec.
Maintenance
Related MCP Connectors
Music & audio for AI agents: 50+ AI instruments play your MIDI, stems, audio to MIDI, Logic/Ableton
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.
Related MCP Servers
- AlicenseBqualityAmaintenanceA Model Context Protocol server that enables AI agents to create fully mixed and mastered tracks in REAPER DAW, supporting project management, MIDI composition, audio recording, and mixing automation.58161MIT
- 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.243MIT
- AlicenseBqualityAmaintenanceConnects AI assistants to REAPER for music production, enabling full control over tracks, MIDI, mixing, mastering, and audio analysis through 153 tools across 24 modules.174109Apache 2.0
- AlicenseCqualityAmaintenanceA comprehensive MCP server that enables AI assistants to control REAPER DAW for mixing, mastering, MIDI composition, and full music production workflows with 130 tools.1802,055 PyPI97MIT