osc-bridge

io.github.roomi-fields由 GitHub 账号 roomi-fields 发布v0.19.1更新于 Oct 31, 2026

OSC ↔ MIDI bridge for synthesizers and DAWs, with the SynthHub catalogue. A MIDI MCP and OSC MCP.

已验证Streamable HTTP可网页运行知识与记忆开发者工具媒体与设计

概览

AI 生成的概览

把 MIDI/SysEx 硬件合成器与 OSC 软件桥接给助手,并接入 SynthHub 驱动目录和共享预设。

可以做什么
  • 搜索驱动目录,读取设备文档与 OSC 路由
  • 把驱动导出为 OSCQuery JSON 或 MIDNAM
  • 向目录回报驱动测试结果、学到的 MIDI 映射、新驱动与修正
  • 查找、读取、分享、更新版本、评论、收藏和撤回共享预设
  • 通过中继检测、发送和监听用户硬件,并从合成器取回音色
  • 把共享预设载入用户设备,并管理合集、关注、个人资料与账号绑定
适用场景
适合用户希望助手处理合成器、鼓机、控制器或 DAW 的场景:查询设备如何被控制、向真实硬件发送音符与参数变化,或查找并载入共享音色。也适合向目录贡献修正和新设备驱动。
运行要求
可使用托管远程端点,或在本地用 Node.js 运行 npm 包(stdio)。访问硬件需用户打开中继页面并用配对码连接;本地版本需要 MIDI 端口,OSC 目标需要运行中的桥接。未声明任何 API 密钥或环境变量。
安装前请注意
服务器会为每个会话发放匿名账号,并要求助手传入 user_id、改用个人地址以保留该账号,应视为账号处理而非中性默认。载入预设会替换设备当前音色,恢复类操作会覆盖设备内存。分享、评论、收藏和回报会以 CC BY-SA 4.0 公开发布数据。中继检测会向所有端口发送 MIDI 身份请求,目录查询会把端口名和设备身份发送到托管服务。

安装

在 SourceWeft 中

  1. 打开 控制台中的 osc-bridge,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.roomi-fields%2Fosc-bridge/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "osc-bridge": {
      "type": "http",
      "url": "https://mcp.synthhub.roomi-fields.com/mcp"
    }
  }
}

README

osc-bridge

[Release] [CI] [License: AGPL-3.0-or-later] [mcptry]

Declarative OSC bridge for music hardware and software — and an MCP server to drive it from an LLM.

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, its driver; the catalogue of drivers lives on SynthHub, which hands them out one at a time. 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]

Install

Hosted MCP server, nothing to install — the SynthHub server, run by the maintainer of osc-bridge, with the catalogue, trust from real use and the relay to your own hardware:

  • Claude (web, desktop): Settings → Connectors → Add custom connector → https://mcp.synthhub.roomi-fields.com/mcp
  • Claude Code: claude mcp add --transport http synthhub https://mcp.synthhub.roomi-fields.com/mcp
  • Cursor and other clients: {"mcpServers": {"synthhub": {"url": "https://mcp.synthhub.roomi-fields.com/mcp"}}}

On your machine — the MCP server over stdio, with hardware detection and OSC to a running bridge (each driver fetched from SynthHub when needed and kept in a cache; you choose what it shares):

bash
npx -y @roomi-fields/osc-bridge mcp

As a standalone bridge / CLI:

bash
npm install -g @roomi-fields/osc-bridge      # downloads the prebuilt binary# or grab a binary directly from the Releases pageosc-bridge run --device arturia/minilab3 --out-port 4   # a driver id, or a JSON file of yours

MCP client config and the tools → docs/MCP.md. Full quick-start with MIDI port discovery → § Install & quick start.

Why a bridge?

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:

  • CC / NRPN addresses are cryptic
  • SysEx byte formats are hand-rolled per device
  • Bidirectional state (what the device CURRENTLY knows) is hard to track

osc-bridge gives every supported synth a clean, named OSC surface:

supercollider
~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.

Where the drivers come from

The catalogue lives on SynthHub, not in this repository: browse and search it at synthhub.roomi-fields.com. osc-bridge asks the SynthHub server for one driver at a time, when it needs it:

  • osc-bridge run --device korg/minilogue (a driver id) or --device minilogue (a slug: the device's best variant) fetches that driver and keeps it in the cache (~/.cache/osc-bridge/drivers/, or $XDG_CACHE_HOME, %LOCALAPPDATA%), then downloads it again only when the server's copy changed;
  • osc-bridge detect and the MCP tool detect_hardware ask the server which makers' identity requests to send, then send it the names of the MIDI ports found here and what the devices answered, and it names the matching drivers and firmware; list_devices searches the catalogue there;
  • offline (osc-bridge privacy --offline on, OSC_BRIDGE_OFFLINE=1), only the drivers already cached are used and nothing is sent.

These requests present the anonymous account of this machine. A JSON file on your machine is used as it is (--device my-synth.json, osc-bridge mcp --devices-dir my-drivers/).

What makes it different

  • One JSON = one driver. Adding a synth is ~30 lines of declarative JSON — CC numbers, SysEx frame templates, optional parameter tables. No Rust, no bindings, no build step. Ship a PR, osc-bridge run picks it up.
  • A shared catalogue. Prophets, Oberheims, the Yamaha DX family, MatrixBrute, Hydrasynth, Virus TI, Digitone, Matrix-1000… the SynthHub catalogue covers most synths, drum machines and DAWs, and grows with what users and agents contribute. Searchable at synthhub.roomi-fields.com.
  • Hardware and software. The same named OSC surface drives a hardware synth over MIDI/SysEx or a DAW / live-coding environment over OSC — Ableton, Bitwig, Reaper, Sonic Pi, SuperCollider, Pure Data, TouchDesigner, VCV Rack. See § Software targets.
  • An MCP server built in. osc-bridge mcp exposes the SynthHub 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.
  • Honest provenance. Each device declares its source in _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.
  • Bidirectional out of the box. Incoming MIDI (knob turns, SysEx replies, NRPN) is decoded and re-emitted as OSC. Multi-client fan-out is a --osc-client flag.
  • N-to-N orchestration. One process can drive several synths at once (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.
  • First-class reconfigurable controllers (Electra One MK2). Upload a generated preset as one OSC call; the bridge parses the JSON, reconfigures the device over SysEx, and dynamically rewires its own CC↔OSC routing so each knob on the new layout is reachable by name. Self-describing over OSC: /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.
  • Escape hatch when JSON isn't enough. For devices with checksums, quirky scaling, or stateful protocols, an optional per-parameter 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.
  • Runtime you can trust. Rate-limiting per device, backpressure-aware, zero-alloc hot path, no GC. Single static binary on Windows / Linux / macOS.

Supported devices

The catalogue — synths, drum machines, controllers, DAWs and live-coding environments, with each driver's source and how far users confirmed it — is on SynthHub:

Each driver declares its source in _sources[]: ✅ hardware-verified, ✅ software-verified, 📘 vendor-doc, 📡 vendor-osc-api / 📡 third-party-osc, 🎛️ electra-preset, 📦 pencilresearch.

Share your own device

New here? The 30-minute tutorial builds a working driver end to end. Otherwise — three common cases, pick yours:

Your synth isn't listed → write its driver and send it to SynthHub.

  1. Find a source: vendor programmer's reference, MIDI implementation PDF, or a canonical CSV.
  2. Follow docs/DEVICE_JSON_SCHEMA.md; the driver of a similar device (/api/v1/devices/<id>.json on SynthHub, or the copy in your cache) is a good template.
  3. Check it: osc-bridge lint my-synth.json, then osc-bridge run --device my-synth.json on the device.
  4. Contribute it: from an MCP client, the submit_driver tool (it is checked, then added to the catalogue); or open an issue here with the file.

A driver is wrong, or you tested it on the hardware → tell SynthHub: report_result and report_mapping (MCP) record what works on which firmware, and submit_fix turns learned mappings into a corrected driver.

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.

Reconfigurable controllers (Electra One MK2) — the scripts stress-test

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):

  • Native JSON codec (ob.json_decode / ob.json_encode) — parses a full Electra preset (up to 100 KB of nested pages/devices/groups/controls/overlays) in a single Lua block, under the 500 ms preset_ingest profile.
  • Persistent per-device state (ob.state) — the driver stores the active preset name so /electra1/preset/current can report it on demand.
  • Dynamic CC↔OSC route registration (ob.register_cc_route / ob.clear_routes / ob.set_current_page) — every preset upload rebuilds the bridge's routing table from scratch, zero restart.
  • Multi-block SysEx emission (ob.emit_sysex) — the upload script emits the wrapped SysEx preset data block directly from Lua.
  • Outbound OSC emission (ob.emit_osc) — powers the introspection endpoints: /routes/list, /preset/current, /page/current.
  • Reply scripts with matched bindings (ctx.bindings) — when the device reports a page switch over SysEx, a reply script updates the bridge's active page so CC routing tracks the hardware UI automatically.
  • Companion markdown auto-load — the driver's notes (electra-one.md, next to its JSON) are loaded 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.

What the bridge does

 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 3

Discovery from zero

Every piece of device-specific knowledge is exposed over OSC — clients never hardcode slugification rules, page indexing, or SysEx opcodes:

SendReceive
/bridge/statusOne /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/listN× /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.

Generalising to other reconfigurable controllers

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.

Install & quick start

Prebuilt binaries

Grab the latest osc-bridge.exe (Windows), osc-bridge (Linux/macOS) from the Releases page.

From source

git clone https://github.com/roomi-fields/osc-bridgecd osc-bridgecargo build --release./target/release/osc-bridge list

Minimal MiniLab 3 workflow

bash
# 1. Find your synth, its driver and its MIDI portsosc-bridge detect
# 2. Start the bridgeosc-bridge run --device arturia/minilab3 \  --out-port 4 --in-port 0 \  --bind 127.0.0.1:7777 --osc-client 127.0.0.1:8888
# 3. From another terminal, send OSCosc-bridge osc-send /minilab3/display/text "Hello" "World"osc-bridge osc-send /minilab3/pad/0/color 127 0 0osc-bridge osc-send /minilab3/knob/3/cc_number 100

Incoming 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/get

Browser clients (OSC over WebSocket)

Browsers can't speak UDP. Pass --ws-bind to expose the same OSC surface over WebSocket:

bash
osc-bridge run --device arturia/minilab3 \  --out-port 4 --in-port 0 --ws-bind 127.0.0.1:7890

Binary WS frames carry raw OSC packets — the exact bytes the UDP transport uses, so a minimal dependency-free OSC encoder/decoder in JS covers both directions. Every connected WS client behaves like an extra --osc-client: it receives all outbound events (decoded MIDI-in, SysEx replies, /bridge/status) and its frames go through the same dispatch as UDP. Under orchestrate, set ws_bind = "127.0.0.1:7890" in the [osc] section of bridge.toml. Disabled by default; keep it on 127.0.0.1 unless you really want LAN clients.

Only pages served from this machine (localhost, 127.0.0.1) and non-browser clients may connect: any other website open in your browser is refused (HTTP 403), so it cannot reach your synths. Allow a specific site with --ws-allow-origin https://example.org (repeatable; null for file:// pages; * for any), or ws_allow_origins = [...] in bridge.toml.

OSCQuery and MIDNAM

--oscquery-bind 127.0.0.1:7891 (or oscquery_bind in the [osc] section of bridge.toml) answers OSCQuery requests: http://127.0.0.1:7891/ lists every OSC address the bridge answers, with its types and ranges, so OSCQuery clients build their controls by themselves. osc-bridge export --device <driver> --format oscquery|midnam writes the same namespace, or the driver's MIDI names as a MIDNAM file for DAWs. See docs/EXPORT.md.

Device not showing up? (Windows 11 24H2+)

Since 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:

  1. Device Manager → Sound, video and game controllers → right-click the device → Update Driver.
  2. Browse my computer for drivers → Let me pick from a list of available drivers on my computer.
  3. Select USB Audio Device (FR: "Périphérique audio USB"). If not visible, uncheck "Show compatible hardware" and look under the Standard USB section.
  4. Install, then unplug/replug the USB cable to force MME to re-enumerate.
  5. 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.

Ergonomics

Which synth is plugged in, and which driver fits?

osc-bridge detect

Lists MIDI ports, asks each device who it is (the standard MIDI Identity Request, then the makers' own requests the drivers name — harmless), has the SynthHub server match the answers against the drivers' identity blocks (offline: the drivers cached here), with the firmware read from them, and prints a ready-to-run osc-bridge run line. --no-probe matches by port name only.

Back up and restore presets (SysEx librarian)

osc-bridge backup  --in-port minilab --out backups/minilab3.syx   # then start the dump on the deviceosc-bridge restore --out-port minilab backups/minilab3.syx        # overwrites the device's memory

Ports take an index or a name fragment. backup --request "F0 … F7" --out-port … sends a dump request first; restore --gap-ms paces older devices.

Drum machines: play sounds by name

Drivers with a drum map expose each voice: /drm1_mkiv/drum/kick 110 fires the Vermona DRM1 MKIV kick at velocity 110 (note 36, channel 10). When a device documents several trigger modes, the address carries the mode, e.g. /tr_8s/drum/default_note_map/bass_drum. See DEVICE_JSON_SCHEMA.md.

Explore a device spec without connecting anything

osc-bridge inspect arturia/minilab3

Live-debug the OSC traffic

osc-bridge osc-listen --bind 127.0.0.1:8888

Send raw SysEx (power user)

osc-bridge osc-send /minilab3/raw/syx "F0 00 20 6B 7F 42 02 00 16 04 7F 00 00 F7"

How device JSONs work

A device file declares three things:

  1. Framing — the SysEx header/footer bytes.
  2. Commands — high-level OSC routes (pad colors, display text, preset recall) that build frames by substituting OSC args into placeholder templates.
  3. Params — a flat table of parameter addresses for bulk GET/SET via a shared opcode.

Example snippet (the arturia/minilab3 driver):

jsonc
{  "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]}    ]  }}

Software targets — DAWs and live coding environments

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:

TargetModeStatus
Ableton Live 12.2.7 + AbletonOSCdeclarative✅ software-verified
Bitwig Studio + DrivenByMossdeclarative📡 third-party-osc
Reaper 7 (Default.ReaperOSC)declarative📡 vendor-osc-api
Sonic Pi 4.5passthrough📡 vendor-osc-api
SuperCollider sclang 3.13passthrough📡 vendor-osc-api
Pure Data 0.55-xpassthrough📡 vendor-osc-api
TouchDesigner 2023passthrough📡 vendor-osc-api
VCV Rack 2 + vcv-osc pluginpassthrough📡 third-party-osc

Each driver comes with its .md notes on SynthHub that document 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:

toml
[osc]bind = "127.0.0.1:7777"clients = ["127.0.0.1:8888"]# ws_bind = "127.0.0.1:7890"   # optional — browser clients over WebSocket
[[devices]]spec = "arturia/minilab3"      # a driver id or slug, or a JSON filemidi_out_port = 4midi_in_port = 0
[[devices]]spec = "ableton/live.third-party-osc.fw-12.2"   # AbletonOSC: no MIDI port needed
[[routes]]from = "/minilab3/cc/74"to = "/ableton/track/0/volume"map.from = [0, 127]map.to = [0, 1]

Use from Claude via MCP

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 SynthHub catalogue, read a device's OSC surface, and send OSC to synths and DAWs.

Hosted — add https://mcp.synthhub.roomi-fields.com/mcp as a remote MCP server (see Install). Nothing to install; your synth joins through the relay page, synthhub.roomi-fields.com/connect.

On your machine:

jsonc
{  "mcpServers": {    "osc-bridge": {      "command": "npx",      "args": ["-y", "@roomi-fields/osc-bridge", "mcp"]    }  }}

Nine local tools — list_devices, get_device_docs, list_routes, export_device, send, get_status, detect_hardware, backup_presets, restore_presets — plus the server's: reports, trust, contributions and shared presets (find, load, take from the synth, share). 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.

Project genesis

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.

License

AGPL-3.0-or-later. Running a modified version as a network service obliges you to offer its source to the users of that service. The sysex-controls reverse engineering that seeded our MiniLab 3 parameter table is GPL-3.0, which GPL-3.0 section 13 allows to combine with AGPL-3.0 code.

Third-party device data

The driver catalogue is SynthHub's, each driver with the credit and licence of its sources in _sources[]. The few drivers kept here for the tests (tests/fixtures/devices/) keep theirs: those of type pencilresearch are adapted from MIDI Guide by Pencil Research and contributors, licensed CC BY-SA 4.0 (source: pencilresearch/midi); each records the licence, the attribution and the exact upstream CSV and commit; the change made is the conversion of CSV rows to the osc-bridge JSON schema.

来源:README.md,提交 365159a

工具

29

list_devices

List devices

Find device drivers in the catalogue of synths, drum machines, controllers and DAWs. Without arguments it lists them all; `query` keeps drivers whose vendor, name or slug contain every word (e.g. 'korg minilogue'). Returns name, vendor, OSC prefix (slug), kind, source tier and firmware version when the source states one. Pass the slug to list_routes for the full CC/NRPN/SysEx map.

输入参数kindlimitqueryvendoruser_id

get_device_docs

Get device docs

Fetch the markdown companion documentation for one device, if present. The slug is the device's OSC prefix without the leading slash (e.g. 'ableton' for /ableton).

输入参数slug必填user_id

list_routes

List device routes

Return the OSC routes a device exposes: declarative commands (OSC paths it accepts), cc/nrpn params, sysex params, named note triggers (drum sounds), and reply patterns. Use this to discover what a device can do.

输入参数slug必填user_id

export_device

Export a driver

Write one driver in a format other tools read: 'oscquery' gives its OSC namespace as OSCQuery JSON (every route with type tags, ranges and access, for OSC controllers and browsers); 'midnam' gives its MIDI names as a MIDI Name Document (controllers incl. NRPN/RPN, named values, drum notes per channel, for DAWs such as Ardour or Logic). Both carry the credit and licence of the driver's sources. The document is the text content; an OSCQuery namespace is large (every address, each CC 0-127 included).

输入参数device必填format必填user_id

report_result

Report a test result

Tell the catalogue how a driver behaved on a real device, after testing it: 'works', 'fails' or 'partial', for the whole driver or one OSC address (from list_routes). Give the firmware version, and the device's reply to the MIDI Identity Request (F0 7E 7F 06 01 F7) as identity_hex when you can: trust is counted per firmware, so a failure on another firmware does not count against the driver, and a report of unknown firmware cannot be placed. Several accounts that agree on one firmware mark the driver usage-verified there; a report that several others contradict is rolled back and puts its account under review. Report only what was actually tested.

输入参数notedevice必填addressoutcome必填user_idfirmwareidentity_hex

get_trust

Get a driver's trust

How far a driver has been confirmed by people who used it, per firmware: status (unreported, unconfirmed, usage-verified, firmware-dependent, failing, disputed), how many users report it works / fails / partly works, each firmware's own status, the device identities seen for each firmware, and the same per OSC address. needs_firmware: true means reports disagree and some have no firmware — identify the device before reporting (see learn). Check it before relying on a driver, together with its source_tier.

输入参数device必填user_id

report_mapping

Report what a control sends

Teach the catalogue which MIDI message a control really sends: after the user moved one control on the device (see relay_listen), give the driver address it is (from list_routes) — or, for a control the driver lacks, its panel label — and the CC, NRPN or note it sent, with the firmware and the device's Identity Reply when you have them. When several accounts observe the same thing on one firmware the mapping is learned; get_trust shows learned mappings and where they differ from the driver.

输入参数ccnotelabeldevice必填addresschanneluser_idfirmwarenrpn_lsbnrpn_msbidentity_hex

submit_driver

Contribute a driver

Contribute a driver for a device the catalogue lacks (or a better one): the full driver file as a JSON object, in the osc-bridge device schema (device.name, device.vendor, device.osc_prefix, and cc_params / params / commands / triggers — see https://synthhub.roomi-fields.com/DEVICE_JSON_SCHEMA/). It is checked, then merged into the SynthHub catalogue by the merge job if it parses, lints and passes the tests, as its own file of source 'agent-contributed'. Say where the data comes from (manual page, tested on the device).

输入参数notedriver必填sourceuser_idfirmware

submit_fix

Contribute a fix from learned mappings

Contribute a corrected variant of a driver from what the catalogue learned: where learned mappings (get_trust → mappings, differs: true) disagree with the driver on one firmware, builds a copy of the driver with the learned CC / NRPN numbers, as a new file for that firmware, and queues it for the merge job.

输入参数device必填user_idfirmware

get_contribution

Contribution status

Where a contribution stands: pending (waiting for the merge job), merged (with its pull request), rejected (with the reason), or held (its account is under review).

输入参数id必填user_id

share_preset

Share a preset

Share something the user made on a device with every SynthHub user, under CC BY-SA 4.0: a sound, a sequence or pattern, a kit, a project, a bank of their own sounds, or a MIDI clip any device can play. Its content: the device's own data (SysEx, e.g. from backup_presets), settings by driver address (from list_routes, e.g. {'/filter/cutoff': [90]}, which also works for devices without dumps), and/or a standard MIDI file. Only what the user made: never factory presets, nor sounds or sequences bought or downloaded from others — set own_sound only after asking the user. Made from someone else's shared preset? Pass derived_from: it credits them, as the licence requires. Describe it well (category, genres, tags, tempo, key, tips): that is how people find it. The same content shared twice returns the existing id; the author publishes new versions with update_preset and can withdraw it (withdraw_preset). Through a relay, the device data can be captured from the device itself: pass code and start the dump from the device's menu during the call, or give request_hex (the device's dump-request message, which the user accepts at the relay). An audio preview is added by its author with PUT /u/<account>/v1/presets/<id>/audio (MP3, Ogg, M4A or WebM, 1 MB at most).

输入参数hexkeycodekindname必填porttagstipstempodevice必填genresseconds另有 10 个

update_preset

Update a preset

Publish a new version of a preset this account shared: new content (hex, file, settings or midi_file) makes a new version, kept with a change note — earlier versions stay available; the description fields alone change it in place. Someone else's preset: share yours with derived_from instead.

输入参数id必填hexkeynametagstipstempogenresuser_idcategoryfirmwaresettings另有 3 个

find_presets

Find presets

Search what SynthHub users shared (CC BY-SA 4.0): sounds, sequences, kits, projects, banks, MIDI clips. Filter by device, kind, category, genre, tag, author (pseudonym) or words; sort by newest, most stars, most loaded into a device or most trusted (confirmed on real devices). Returns, per preset, its id, name, kind, device, description, author, version, whether it has device data, settings, a MIDI file or an audio preview (URL), and its counts. Get one with get_preset.

输入参数tagkindsortgenrelimitqueryauthordeviceoffsetuser_idcategory

get_preset

Get a preset

One shared preset in full: its content (SysEx hex, settings by driver address, MIDI file), description and playing tips, versions with their change notes, what it was derived from and its derivatives (remixes), comments, preview URLs, author, licence and attribution line, trust and counts. Load it with load_preset; credit it as the attribution line says when you publish something made from it.

输入参数id必填user_idversion

report_preset

Report on a preset

Tell SynthHub how a shared preset behaved once loaded on a real device: 'works' (it loaded and sounds as described), 'fails' (refused, wrong sound), or 'factory' (it is a factory preset or someone else's sound: presets that several users flag are hidden until reviewed). Give the firmware.

输入参数id必填noteoutcome必填user_idfirmware

withdraw_preset

Withdraw a preset

Withdraw a preset this account shared: it is no longer listed nor served. Copies others already made stay under CC BY-SA.

输入参数id必填user_id

comment_preset

Comment on a preset

Comment on a shared preset — how it sounds, how you used it, what you changed — optionally attaching your remix (a preset you shared with derived_from). Comments are public at once. Also: remove one of this account's comments (remove), or flag someone else's as abusive or off-topic (flag); comments several accounts flag are hidden until reviewed.

输入参数idflagtextremixremoveuser_id

star_preset

Star a preset

Star a shared preset for this account, as on GitHub (on: false takes the star back). Without id, lists the presets this account starred.

输入参数idonuser_id

preset_collection

Preset collections

Collections of shared presets, public, made by one account (e.g. 'Dark basses for minilogue'). action: create (name, description), rename (collection, name, description), add or remove (collection, id), delete (collection), get (collection: its presets), list (this account's collections, or author: someone's).

输入参数idnameaction必填authoruser_idcollectiondescription

follow_author

Follow an author

Follow an author of shared presets (by pseudonym), or stop (on: false); with author alone and on omitted, shows their page: profile, presets, followers. Without author, lists the newest presets of the authors this account follows.

输入参数onlimitauthoruser_id

set_profile

Set the public profile

Set the public profile shown on this account's author page and with its shared presets and comments, instead of its pseudonym alone: display name, link (https), a few words, the presets put first, where they are, more links, their instruments and a README. A field left out stays as it is; an empty one is cleared. Ask the user what they want shown; all of it is public.

输入参数biogearlinknameaboutlinksuser_idfeaturedlocation

relay_status

Relay status

Check a relay: the user opened https://synthhub.roomi-fields.com/connect/ (or ran osc-bridge connect) and gave you its pairing code. Returns the MIDI output and input ports of their machine, and devices: the driver the user confirmed for each port on the page (use it directly, no detection needed). Nothing is sent to the hardware.

输入参数code必填user_id

relay_detect

Detect devices through a relay

Find which devices are connected to the user's machine through a relay: sends the MIDI Identity Request (F0 7E 7F 06 01 F7, changes nothing on the device) to every output and matches the answers — manufacturer, model, firmware version — against the drivers' identity blocks. With maker_requests, also sends the makers' own identity requests the drivers name (they change nothing either, but the relay asks the user to accept them, once per output: tell the user first), which recognise devices that ignore the universal one. Returns the best driver ids (recognised_by and firmware when an identity block recognised the device) and identity_hex to pass to report_result. A device that does not answer is found by its knobs with listen_ms (by_controls), or by what people confirmed of its port name (learned); when several remain, ask names the control to have the user turn next (expect: what each candidate would send), then call again with listen_ms.

输入参数code必填user_idlisten_mstimeout_msmaker_requests

relay_send

Send through a relay

Play or set something on the user's hardware through a relay: give a driver (id or slug) and one of its OSC addresses from list_routes with its arguments (e.g. address '/filter/cutoff', args [64]; '/note/on', args [60, 100]) — the server turns it into the right CC, NRPN, note or SysEx message. Or give raw MIDI bytes as hex. Values are the device's own numbers, clamped to the parameter's range. Any SysEx but the Identity Request (patch dumps, stores, settings, preset restores) may overwrite the device's memory: the relay asks the user to accept it first and this call waits for the answer (up to 2 minutes), so tell the user what you are about to send.

输入参数hexargscode必填portdevicegap_msaddressuser_id

relay_listen

Listen through a relay

Listen to what the user's hardware sends through a relay for a few seconds: notes, CC, NRPN, SysEx, decoded. With a device, each CC or NRPN that moved is matched to the driver's OSC addresses — ask the user to move one control on the device while listening to learn which address it is, or to check that the driver's map is right (then record what you saw with report_mapping, so the catalogue learns it).

输入参数code必填devicesecondsuser_id

take_sound

Take a synth's sound through a relay

Take the sound the user's synth is playing — or one of its stored programs — straight from the synth through a relay, with its name. The synth is found among those SynthHub's librarian can talk to (the KnobKraft Orm adaptations, about 90 synths) by the identity and detect messages, then asked for its sound. The person accepts each step at the relay (finding the synth, asking it): tell them first. To share it: ask the user whether they made this sound themselves (never a factory preset, nor one bought or downloaded), then call share_preset with the device, name, hex, librarian and firmware returned here, and own_sound: true. When several synths answer, or none did, call again with port.

输入参数code必填portprogramuser_id

load_preset

Load a preset through a relay

Load a shared preset (find_presets, get_preset) into the user's device through a relay: its settings are sent through the driver, its patch data as SysEx — which replaces the sound the device holds, so the relay asks the user to accept it and this call waits for the answer (up to 2 minutes): tell the user first. Afterwards, tell SynthHub how it went with report_preset.

输入参数id必填code必填portdevicegap_msuser_id

claim_presets

Claim imported presets

Claim presets SynthHub imported from another site (their page says 'imported', with the author's name and page there) when the user is that author: give the id of one of them; the server answers with a code for the user to add to their author page at that site (profile or bio). Once it is there, call again with verify: true: every preset imported from that author becomes the user's, to edit or withdraw.

输入参数id必填verifyuser_id

版本历史

6
  1. v0.19.1最新Oct 31, 2026
  2. v0.19.0Oct 31, 2026
  3. v0.17.0Oct 29, 2026
  4. v0.16.0Oct 24, 2026
  5. v0.15.0Oct 23, 2026
  6. v0.10.1Sep 16, 2026

评分

已满足适用检查项的 100%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分