Metadata-Version: 2.4
Name: postfader-fl-studio-mcp
Version: 0.10.0
Summary: Unofficial local MCP bridge for verified FL Studio mixer and plug-in control on macOS
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/synopsys0/postfader-fl-studio-mcp
Project-URL: Repository, https://github.com/synopsys0/postfader-fl-studio-mcp
Project-URL: Issues, https://github.com/synopsys0/postfader-fl-studio-mcp/issues
Project-URL: Documentation, https://github.com/synopsys0/postfader-fl-studio-mcp#readme
Keywords: fl-studio,mcp,model-context-protocol,midi,music-production
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: MacOS X
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: anyio<5,>=4.5
Requires-Dist: mcp[cli]<3,>=2.0.0
Requires-Dist: numpy<3,>=1.24
Requires-Dist: scipy<2,>=1.10
Requires-Dist: soundfile<1,>=0.12
Requires-Dist: pyloudnorm<1,>=0.1.1
Requires-Dist: python-rtmidi<2,>=1.5
Requires-Dist: pydantic<3,>=2.12
Provides-Extra: test
Requires-Dist: tomli>=2; python_version < "3.11" and extra == "test"
Provides-Extra: dev
Requires-Dist: fl-studio-api-stubs<38,>=37; extra == "dev"
Requires-Dist: tomli>=2; python_version < "3.11" and extra == "dev"
Dynamic: license-file

<div align="center">

# Postfader

**An AI copilot for FL Studio**

Inspect a running project, measure your bounces, and make verified mixer and
plug-in changes — from Claude or any MCP client.

[![CI](https://github.com/synopsys0/postfader-fl-studio-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/synopsys0/postfader-fl-studio-mcp/actions/workflows/ci.yml)
[![License](https://img.shields.io/badge/license-Apache_2.0-blue)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.10%20--%203.14-blue)](https://www.python.org/downloads/)
[![Platform](https://img.shields.io/badge/platform-macOS-lightgrey)](#requirements)
[![MCP](https://img.shields.io/badge/Model_Context_Protocol-server-8A2BE2)](https://modelcontextprotocol.io)

[Setup](docs/setup.md) · [Tools](docs/tool-contracts.md) ·
[Plug-ins](docs/plugin-support.md) · [Architecture](docs/architecture.md) ·
[Security](SECURITY.md)

</div>

---

A local Model Context Protocol server and MIDI bridge for FL Studio 2026 on
macOS. Reads are always available. Writes are off until you turn them on, and
every one of them is read back from FL Studio and reported honestly.

An illustration of the shape of a session — not a captured transcript:

```
You:     the vocal is fighting the synth around 3k
Client:  → fl_list_mixer_tracks        reads the mixer and its routing
         → audio_analyze_masking       measures the overlap between two bounces
         → fl_set_track_eq             cuts one EQ band on one track
                                       verified: true
```

## Why another FL Studio MCP server

FL Studio accepts scripted writes and then silently ignores some of them. Most
connectors report the write as sent. Postfader reads the control back on a later
idle tick and tells you `verified: true` or `verified: false` — and treats a
false as the headline of the result, not a footnote.

A write does repeat its setter call within its own attempt, because FL drops a
lone one — but a write that comes back unproven is never replayed for you, a
write that landed is never rolled back, and where FL's own undo cannot be
relied on the response says so instead of assuming.

| | |
|---|---|
| **Verified writes** | Every change is read back from FL and reported |
| **Read-only by default** | Writes need a flag set on the FL Studio process itself |
| **Narrow on purpose** | 24 tools, each with a defined contract, not a generic API bridge |
| **No plug-in database** | Parameters are discovered at runtime; nothing to add per plug-in |
| **Hermetic tests** | 582 checks with a fake FL API — no DAW, no MIDI device, no user audio |

## Status

A macOS-only beta, validated on Apple silicon with FL Studio 2026 Producer
Edition 26.1.3 build 5336, MIDI scripting API 44, and Python 3.10 or newer.
Other FL Studio editions and Intel Macs may work but are not currently
validated; Windows is not supported by this release.

This repository contains no user-created FL Studio projects, recordings, stems,
samples, presets, mix exports, or session-derived evidence. Its three audio
fixtures are deterministic and generated by a script in the repository.

## What it provides

The server exposes 24 MCP tools:

- **10 inspection tools** for capabilities, project and transport state,
  Playlist selection observations, mixer tracks and routing, loaded effects,
  and bounded plug-in parameter maps.
- **10 opt-in write tools** for mixer volume, pan, mute, name, built-in EQ,
  sends, send levels, and plug-in parameters by normalized value, displayed
  number, or option text.
- **4 audio tools** for file analysis, reference comparison,
  vocal/instrument masking measurements, and recent-bounce discovery.

The FL Studio scripting API exposes controls but no live audio buffers. Audio
tools therefore operate on files you explicitly export or record to disk.

## Safety model

> Writes are disabled by default. When enabled, mutating tools apply changes
> immediately to the open FL Studio project. Readback verifies whether a
> control moved; it is not an automatic rollback, and FL may not create a
> usable undo point. Work on a copy until you trust the workflow.

The write surface is intentionally narrow:

1. Each write states one absolute target rather than nudging or toggling.
2. FL Studio is read back on a later idle tick and the result reports
   `verified: true` or `verified: false`.
3. Mixer track 0 (Master) is refused unless `allow_master` is explicitly true.
4. Each write requests an undo point and reports whether one was observed.
5. The bridge never calls `saveProject`; changes can still be saved later by
   FL Studio or by the user.
6. Writes are absent from the active bridge allowlist unless FL Studio itself
   was launched with `FL_BRIDGE_ENABLE_WRITES=1`.

`fl_set_plugin_param_option` must sweep an enumerated control to discover the
available option text because FL Studio exposes no enumeration API. Do not use
write tools while recording or on irreplaceable material.

## Plug-in compatibility

There is no supported-plug-in list and no per-plug-in profiles: parameters are
discovered at runtime, so a plug-in needs no support added for it. What varies
is how much of a large parameter map a bounded scan can see, and whether FL
reports a given control at all. See
[Plug-in support](docs/plugin-support.md) for those bounds, how to raise them,
and how to add your own plug-in to the validated-against table.

## Requirements

- macOS with CoreMIDI and an enabled IAC Driver bus
- FL Studio 2026 version 26.1.3 build 5336 or newer
- MIDI scripting API 44 or newer
- Python 3.10 or newer
- An MCP-compatible client

Launch FL Studio once before installing so its user settings folders exist.

## Install

Two paths. Both put the same bridge in the same place — `scripts/install.sh`
calls the same installer the console command does, so they cannot drift.

**From PyPI**, if you just want to use it:

```bash
pip install postfader-fl-studio-mcp
postfader-install-bridge
```

**From a clone**, if you want the test suite and the validation scripts:

```bash
git clone https://github.com/synopsys0/postfader-fl-studio-mcp.git
cd postfader-fl-studio-mcp
./scripts/install.sh
```

If FL Studio's user-data folder is somewhere other than
`~/Documents/Image-Line/FL Studio`, say so — every entry point honours it:

```bash
postfader-install-bridge --user-data-dir "/absolute/path/to/FL Studio"
```

```bash
FL_STUDIO_USER_DATA_DIR="/absolute/path/to/FL Studio" ./scripts/install.sh
```

Then, in FL Studio:

1. Open **Audio MIDI Setup → Window → Show MIDI Studio**.
2. Open **IAC Driver**, enable **Device is online**, and apply the change.
3. In FL Studio, open **Options → MIDI settings → Input**.
4. Select the IAC port, enable it, and set **Controller type** to
   `Universal Bridge`. Note the **Port** number it is given.
5. In the same dialog, under **Output**, select the same IAC port and give it
   **the same Port number**. The bridge replies over MIDI, so it refuses to
   start without this and Script output will say so.
6. Open **View → Script output** and press **Reload script**. The output should
   end with `ready: MIDI SysEx`.
7. Verify the installation:

   ```bash
   postfader-doctor
   ```

   From a clone, `./.venv/bin/python scripts/doctor.py` runs the same checks,
   and `./scripts/inspect_readonly.py --capabilities` prints what the server
   can currently see.

See [Setup and usage](docs/setup.md) for detailed client configuration and
troubleshooting.

## MCP client configuration

The installer writes a `.mcp.json` **inside this checkout**, with relative
paths. That is deliberately the narrow case: it works when your client is
launched from the connector directory, and it is the quickest way to try the
server. It is not how you would normally live with it.

### Using it from your own projects

To reach FL Studio while working anywhere else, register the server once at
user scope with absolute paths. For Claude Code:

```bash
claude mcp add fl-studio --scope user \
    --env FL_BRIDGE_ENABLE_MIDI=1 \
    -- /absolute/path/to/postfader-fl-studio-mcp/.venv/bin/python \
       -m fl_studio_mcp.mcp_server
```

`--scope user` is the part that matters: a project-scoped entry only loads
inside the directory it belongs to, which is why the installer's `.mcp.json`
does not follow you around. Substitute your real checkout path — the venv
interpreter must be named absolutely, because a relative command resolves
against wherever the client happened to start.

For a client with no CLI, put the same absolute-path block in whichever config
file that client treats as global rather than per-project:

```json
{
  "mcpServers": {
    "fl-studio": {
      "command": "/absolute/path/to/postfader-fl-studio-mcp/.venv/bin/python",
      "args": ["-m", "fl_studio_mcp.mcp_server"],
      "cwd": "/absolute/path/to/postfader-fl-studio-mcp",
      "env": {
        "FL_BRIDGE_ENABLE_MIDI": "1"
      }
    }
  }
}
```

Do not assume that an MCP client expands `~` or shell variables in JSON paths;
write them out in full. `.mcp.json.example` in this repository shows the same
shape with relative paths, for the launched-from-the-checkout case only.

The Python distribution is `postfader-fl-studio-mcp`. The import path remains
`fl_studio_mcp`, the console command remains `fl-studio-mcp`, and the MCP
server ID is `fl-studio`.

Only one process can own the IAC port at a time, so if you register the server
at user scope, close any project-scoped copy of it first.

## Enabling writes

Quit FL Studio, then launch it from Terminal with:

```bash
FL_BRIDGE_ENABLE_WRITES=1 open -a "FL Studio 2026"
```

The bridge reads this variable once when its script loads. In write mode,
`ping` reports `bridge_mode: "write_test"` and
`verified_writes_enabled: true`. Launch FL Studio normally to return to its
read-only mode. Do not put `FL_BRIDGE_ENABLE_WRITES` in the MCP server's
environment; it must be present in the FL Studio process.

## Important limitations

- The bridge cannot insert, remove, or reorder plug-ins.
- FL Studio's scripted per-slot bypass and wet/dry setters are not reliable on
  the validated host and are not exposed as MCP tools.
- The bridge cannot render or access live audio; audio analysis requires a
  file on disk.
- Playlist selection endpoints are returned as raw observations and are
  marked unsafe for automated rendering.
- Unprofiled plug-in parameters are readable, but the bridge does not claim to
  know their musical meaning or whether a target value is appropriate.
- Readback verifies observed control movement, not audible correctness.
- The local IAC transport is shared and unauthenticated, and only one bridge
  client can own it at a time.

See [FL Studio constraints](docs/fl-constraints.md) for the technical details.

## Privacy and security

The MCP server and bridge run locally and implement no telemetry or hosted
service. Your MCP client may send tool arguments and results to its model
provider; review that client's privacy policy.

Audio measurement tools can read an absolute audio-file path supplied by the
MCP client. Results include measurements, a canonical path, and a file hash,
but not the audio samples themselves. Recent-bounce discovery searches a
bounded set of FL Studio output folders. Run the bridge only with a trusted MCP
client on a trusted, single-user Mac. See [SECURITY.md](SECURITY.md) for the
complete trust model.

## Documentation

- [Setup and usage](docs/setup.md)
- [Tool and command reference](docs/tool-contracts.md)
- [Plug-in support](docs/plugin-support.md)
- [Architecture](docs/architecture.md)
- [FL Studio constraints](docs/fl-constraints.md)
- [Security policy](SECURITY.md)
- [Contributing](CONTRIBUTING.md)

## Development

Run the hermetic safe suite with:

```bash
./.venv/bin/python scripts/run_safe_tests.py
```

The safe suite uses a fake FL API and deterministic synthetic audio. It does
not require FL Studio, a MIDI device, a user project, or user audio, and it
does not touch the physical IAC bus.

## Non-affiliation

FL Studio is a trademark of Image-Line Software. Postfader is an
independent, unofficial project and is not affiliated with, endorsed by, or
sponsored by Image-Line Software. FL Studio is not distributed with this
repository.

<!-- mcp-name: io.github.synopsys0/postfader-fl-studio-mcp -->
