osc-bridge — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited osc-bridge (Plugin) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
*Declarative OSC bridge for music hardware and software — and an MCP server to drive it from an LLM.*
849 hardware synthesizers over MIDI / SysEx, plus DAWs and live-coding environments over OSC (Ableton, Bitwig, Reaper, Sonic Pi, SuperCollider, Pure Data, TouchDesigner, VCV Rack). Every device gets a clean, named OSC surface described by one JSON file. Drive it from a live-coding client, a DAW, a script, the CLI — or from Claude via the built-in MCP server (a MIDI MCP and OSC MCP).
osc-bridge — clients (OSC clients, the CLI, an LLM via MCP) feed one osc-bridge core that fans out to hardware synthesizers over MIDI/SysEx and music software (Ableton, Bitwig, Reaper, Sonic Pi) over OSC
As an MCP server — drive synths and DAWs from Claude, nothing to install:
npx -y @roomi-fields/osc-bridge mcpAs a standalone bridge / CLI:
npm install -g @roomi-fields/osc-bridge # downloads the prebuilt binary
# or grab a binary directly from the Releases page
osc-bridge run --device devices/arturia/minilab3.json --out-port 4MCP client config and the five tools → docs/MCP.md. Full quick-start with MIDI port discovery → § Install & quick start.
Modern synths — hardware and software alike — expose themselves over MIDI, SysEx, and OSC with proprietary, scattered protocols. Using them from live-coding environments, a DAW, a script, or an LLM is painful:
`osc-bridge` gives every supported synth a clean, named OSC surface:
~mb = NetAddr("127.0.0.1", 7777);
~mb.sendMsg("/minilab3/knob/3/cc_number", 64); // reconfigure knob 3
~mb.sendMsg("/minilab3/pad/0/color", 127, 0, 0); // pad 1 red
~mb.sendMsg("/minilab3/display/text", "Hello", "World");Each synth is described by one JSON file. No Rust recompile required to add a device.
osc-bridge run picks it up.osc-bridge mcp exposes the whole catalogue to Claude (or any MCP client) — a MIDI MCP and OSC MCP. Discover devices, read a device's OSC surface, send OSC to synths and DAWs. See docs/MCP.md._sources[]: ✅ hardware-verified, ✅ software-verified, 📘 vendor-doc, 📡 vendor-osc-api / 📡 third-party-osc, 🎛️ electra-preset, 📦 pencilresearch. You always know whether a mapping was tested on the device or lifted from a spec sheet.--osc-client flag.osc-bridge orchestrate --config bridge.toml), each reachable under its own OSC prefix — so two MatrixBrutes live side-by-side as /matrixbrute-1 and /matrixbrute-2./bridge/docs returns the integration guide, /electra1/routes/list returns the authoritative address table, so clients (or LLM-driven integrators) never hardcode slugification or protocol details. See § Reconfigurable controllers below.transform / per-command script runs Lua 5.4 sandboxed (1 MiB / 10 ms caps, no os/io/loaders). Used sparingly — osc-bridge lint warns on every script use — but it lets the declarative core stay small without giving up on edge cases. See docs/scripting.md.849 devices across 187 vendors — Moog · Arturia · Novation · Korg · Sequential · Dave Smith Instruments · Roland · Yamaha · Elektron · Waldorf · Behringer · Dreadbox · Erica Synths · Polyend · Modal · Expressive E · Bastl · Chase Bliss · Make Noise · Electra One · Tasty Chips · Oberheim · Access · ASM · Black Corporation · Hologram · Strymon · Empress · Meris · Eventide · Ensoniq · Rhodes · Haken · Tubbutec · Ableton · Bitwig · Cockos (Reaper) · Sonic Pi · SuperCollider · Pure Data · TouchDesigner · VCV Rack · and ~85 more.
| Status | Count | Highlight |
|---|---|---|
✅ Hardware-verified (tested on the physical device — scope varies per driver, see _sources in each JSON) | 4 | Arturia MiniLab 3 · Electra One MK2 · Ableton Push 3 · Arturia MatrixBrute (firmware-RE partial) |
| ✅ Software-verified (tested end-to-end against a running instance of the host software) | 1 | Ableton Live 12.2.7 (via AbletonOSC) |
| 📘 Vendor-doc derived (from manufacturer programmer's references — bytes match the spec) | 193 | Novation Launch Control XL 3 · Polyend Synth · … |
| 📡 OSC-API (software targets) — DAWs and live coding environments, declarative or passthrough | 7 | Bitwig Studio · Reaper · Sonic Pi · SuperCollider · Pure Data · TouchDesigner · VCV Rack |
| 🎛️ Electra-preset derived (from the Electra One community preset library — covers SysEx + CC/NRPN, author's editorial choices) | 398 | Prophet 5/10 · Prophet 6 · OB-6 · OB-X8 · Matriarch · Hydrasynth · Virus TI · Digitone · … |
| 📦 Pencilresearch derived (from pencilresearch/midi — CC/NRPN only) | 244 | Moog · Sequential · DSI · Roland · Yamaha · Waldorf · Behringer · Dreadbox · … |
| 🚧 WIP / 📝 stub | 2 | GR Mega (placeholder) |
Searching for your device?
docs/SUPPORTED_DEVICES.md (auto-generated, organised by vendor).Your synth isn't there, or a doc-derived entry (📘 / 📡 / 🎛️ / 📦) needs promoting to ✅ after you test it on hardware? See the next section.
New here? The 30-minute tutorial builds a working driver end to end. Otherwise — three common cases, pick yours:
Your synth isn't listed → open a PR adding devices/<vendor>/<slug>.json.
python3 scripts/import_pencilresearch.py <path-to-csv> — generates the JSON for you.devices/ as a template and follow docs/DEVICE_JSON_SCHEMA.md.cargo run --release -- lint <file> and cargo test --release.python3 scripts/regen_supported_devices.py to refresh the catalogue.new_device.md template.Your synth is listed but not yet `✅`, and you have the hardware → PR promoting it to ✅. Test every route, attach the log, flip the marker. promote_to_verified.md template.
Your synth is listed but a CC is wrong / needs SysEx added → PR updating the JSON. update_device.md template. Especially welcome on pencilresearch-imported devices where SysEx needs to be layered in.
Full contributor guide (schema extensions, bug reports, Lua escape hatch) → CONTRIBUTING.md. For devices whose protocol can't be expressed declaratively, see docs/scripting.md — use sparingly; osc-bridge lint warns on every use.
Most synths have a fixed set of controls — MiniLab 3's knobs always mean the same thing. The Electra One MK2 is different: its 216 controls are defined by a preset that you upload to the device, and the meaning of every CC changes when the preset changes. A static JSON spec can't describe that; the bridge treats it as a first-class case.
This integration is what validates the whole Lua scripting subsystem in anger. The MK2 driver exercises every feature of the scripting.rs layer on real hardware (firmware 4.1.4, verified 2026-04-14):
ob.json_decode / ob.json_encode) — parses a fullElectra preset (up to 100 KB of nested pages/devices/groups/controls/overlays) in a single Lua block, under the 500 ms preset_ingest profile.
ob.state) — the driver stores the activepreset name so /electra1/preset/current can report it on demand.
ob.register_cc_route /ob.clear_routes / ob.set_current_page) — every preset upload rebuilds the bridge's routing table from scratch, zero restart.
ob.emit_sysex) — the upload script emitsthe wrapped SysEx preset data block directly from Lua.
ob.emit_osc) — powers the introspectionendpoints: /routes/list, /preset/current, /page/current.
ctx.bindings) — when the devicereports a page switch over SysEx, a reply script updates the bridge's active page so CC routing tracks the hardware UI automatically.
devices/electra-one/electra-one.md isloaded at startup and served over /bridge/docs, so LLM-driven integrators read the device-specific quirks (hex-color requirement, inputs[{potId}] mandatory, envelope-segment cycling gesture, MIDI port selection, etc.) without any code-side knowledge.
Every item above has a unit test, an end-to-end test against the real .json driver, and a hardware-verified green light. If you're building a driver for another reconfigurable controller (Faderfox custom, programmable MIDI Fighter), the Electra driver is the template — copy its custom_commands block, adapt the JSON→routes parsing to your device's preset format, done.
Kanopi / your client osc-bridge Electra One MK2
───────────────────── ──────────────── ────────────────────
/electra1/preset/upload ───► parse preset JSON (preset_ingest
"<preset JSON>" profile: 500 ms / 4 MiB Lua)
┌─ ob.clear_routes()
├─ ob.register_cc_route × N
│ (one per cc7 control,
│ per-page, with channel)
└─ ob.emit_sysex(…) ──────────► F0 00 21 45 01 01 <json> F7
(reconfigures device)
◄────────── F0 00 21 45 7E 01 … ACK
(user turns knob on page 2) ◄────────── B4 4A 53 (CC#74 ch5 = 83)
route lookup: page=2, ch=4, cc=74
→ /electra1/page2/cutoff 0.65 ───► /electra1/page2/cutoff 0.65
(user switches page on device) ◄────────── F0 00 21 45 7E 06 03 F7
reply.script fires:
ob.set_current_page(3)
───► /electra1/page/switched 3Every piece of device-specific knowledge is exposed over OSC — clients never hardcode slugification rules, page indexing, or SysEx opcodes:
| Send | Receive |
|---|---|
/bridge/status | One /bridge/status/device <slug> <status> per connected device |
/bridge/docs | /bridge/docs/device <slug> <markdown> — full integration guide (the device's companion .md, loaded automatically) |
/electra1/routes/list | N× /electra1/routes/entry <addr> <ch> <cc> <page> <min> <max> then /electra1/routes/done |
/electra1/preset/current | /electra1/preset/current <name> |
/electra1/page/current | /electra1/page/current <n> |
An LLM-driven integrator needs exactly four steps to go from cold start to routing knob turns: /bridge/status → /bridge/docs → /electra1/preset/upload → /electra1/routes/list. Everything else is in the markdown guide embedded in the bridge itself.
The machinery (DynamicRoutes, ob.register_cc_route, ob.emit_sysex, custom_commands, companion .md auto-loading) is device-agnostic. Adding a reconfigurable Faderfox, a custom MIDI Fighter Twister layout, or any programmable controller is the same recipe: a preset-parsing Lua block inside the device JSON that calls ob.register_cc_route per control. No core changes.
Grab the latest osc-bridge.exe (Windows), osc-bridge (Linux/macOS) from the Releases page.
git clone https://github.com/roomi-fields/osc-bridge
cd osc-bridge
cargo build --release
./target/release/osc-bridge list# 1. Find your MIDI port indices
osc-bridge list
# 2. Start the bridge
osc-bridge run --device devices/arturia/minilab3.json \
--out-port 4 --in-port 0 \
--bind 127.0.0.1:7777 --osc-client 127.0.0.1:8888
# 3. From another terminal, send OSC
osc-bridge osc-send /minilab3/display/text "Hello" "World"
osc-bridge osc-send /minilab3/pad/0/color 127 0 0
osc-bridge osc-send /minilab3/knob/3/cc_number 100Incoming MIDI events (knob turns, pads played, pitch-bend, SysEx GET replies) are forwarded to --osc-client as OSC:
/minilab3/cc/18 95 0 ← knob moved
/minilab3/note/on 60 127 0
/minilab3/param/value 0 7 0 0 1 ← reply from a /param/getSince the March 2026 cumulative update (KB5079473), Windows 11 ships Microsoft's new USBMidi2-ACX driver which enforces stricter USB descriptor checks. Devices that pass the old checks but fail the new ones appear in Device Manager with Status: Unknown, or bind to a driver that exposes them only through the new MIDI Services API — invisible to `midir` (and therefore to osc-bridge) which queries the legacy MME interface.
Confirmed affected: Polyend Synth / Play / Tracker / Mess / Step (VID 16D0). Likely affected: any older USB-MIDI device whose descriptor doesn't meet the new spec.
Workaround — force the legacy usbaudio driver:
device → Update Driver.
available drivers on my computer**.
visible, uncheck "Show compatible hardware" and look under the Standard USB section.
osc-bridge list should now show the device.Track Microsoft's progress on KB5079473 if you want a permanent fix — Pete Brown (Microsoft) acknowledged the packet-size issue publicly but classified it as non-blocking. Polyend's firmware-side fix is not announced at the time of writing.
osc-bridge inspect devices/arturia/minilab3.jsonosc-bridge osc-listen --bind 127.0.0.1:8888osc-bridge osc-send /minilab3/raw/syx "F0 00 20 6B 7F 42 02 00 16 04 7F 00 00 F7"A device file declares three things:
Example snippet (devices/arturia/minilab3.json):
{
"commands": [
{
"osc": "/pad/{pad}/color",
"args": [
{"name":"pad","type":"u7","range":[0,7]},
{"name":"r","type":"u7"},
{"name":"g","type":"u7"},
{"name":"b","type":"u7"},
{"name":"mode","type":"enum",
"values":{"user":0,"arturia":1,"daw":2},"default":"user"}
],
"pre": [{"bind":"pad_id","expr":"pad + 4"}],
"frame": [2, "{mode}", 22, "{pad_id}", "{r}", "{g}", "{b}"]
}
],
"params": {
"get_frame": [32, "{pr}", "{p}", "{c}", "{r}"],
"set_frame": [33, "{pr}", "{p}", "{c}", "{r}", "{val}"],
"value_type": "u7",
"entries": [
{"osc":"/global/backlight", "pr":7, "p":0, "c":0, "r":0, "range":[0,1]}
]
}
}osc-bridge isn't only for hardware synthesizers. Since version 0.10 it also treats DAWs and live-coding environments as first-class devices, behind the same /<env> OSC surface as a Prophet or a Matriarch. A driver JSON declares device.transport.kind = "osc" and the bridge forwards OSC to the target's UDP port instead of going through a MIDI cable.
Two flavors:
Declarative drivers — when the host software has a fixed, documented OSC surface (Ableton via AbletonOSC, Bitwig via DrivenByMoss, Reaper's native OSC). The driver enumerates commands[] with typed args, plus replies[] for incoming events.
Passthrough drivers — when the host software has no fixed OSC surface and each user defines their own paths in their project (Sonic Pi, SuperCollider, Pure Data, TouchDesigner, VCV Rack). The driver just declares transport.passthrough_prefix and the bridge forwards anything under /<env>/... verbatim. Replies travel the other way with the prefix added back.
Currently supported:
| Target | Mode | Status |
|---|---|---|
| Ableton Live 12.2.7 + AbletonOSC | declarative | ✅ software-verified |
| Bitwig Studio + DrivenByMoss | declarative | 📡 third-party-osc |
| Reaper 7 (Default.ReaperOSC) | declarative | 📡 vendor-osc-api |
| Sonic Pi 4.5 | passthrough | 📡 vendor-osc-api |
| SuperCollider sclang 3.13 | passthrough | 📡 vendor-osc-api |
| Pure Data 0.55-x | passthrough | 📡 vendor-osc-api |
| TouchDesigner 2023 | passthrough | 📡 vendor-osc-api |
| VCV Rack 2.5 + community OSC plugin | passthrough | 📡 third-party-osc |
Each comes with a .md companion under devices/<vendor>/ that documents the required setup on the host side (Remote Script installation, ports, conventions).
Combined with osc-bridge orchestrate, you can drive a hardware MiniLab 3, an Ableton Live, and a Sonic Pi loop from a single process. With the new [[routes]] section in bridge.toml, a knob turn on the MiniLab can drive an Ableton track volume or a Sonic Pi cue, without writing any client code:
[osc]
bind = "127.0.0.1:7777"
clients = ["127.0.0.1:8888"]
[[devices]]
spec = "devices/arturia/minilab3.json"
midi_out_port = 4
midi_in_port = 0
[[routes]]
from = "/minilab3/cc/74"
to = "/ableton/track/0/volume"
map.from = [0, 127]
map.to = [0, 1]osc-bridge ships a Model Context Protocol server — a MIDI MCP and OSC MCP. Point any MCP client at it and the model can browse the 849-device catalogue, read a device's OSC surface, and send OSC to synths and DAWs.
{
"mcpServers": {
"osc-bridge": {
"command": "npx",
"args": ["-y", "@roomi-fields/osc-bridge", "mcp"]
}
}
}Five tools — list_devices, get_device_docs, list_routes, send, get_status. Then in conversation: "What can the MatrixBrute do? Sweep its filter cutoff." — the model calls list_routes("matrixbrute"), then send. No glue code.
Full setup — Claude Desktop / Cursor config, the workflow, driving software targets → [`docs/MCP.md`](docs/MCP.md).
Started as a MatrixBrute OSC driver (patch format reverse-engineered from the GPL-3 sysex-controls and the community MBPV tool). Grew into a generic declarative bridge once the Arturia protocol family became clear.
GPL-3.0-or-later. Inherits GPL obligations from the sysex-controls reverse engineering that seeded our MiniLab 3 parameter table.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.