Covers DrivenByMoss OSC configuration, architecture explanation, all 204 tools with parameters and descriptions, usage examples, and troubleshooting. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
27 KiB
bitwig-mcp
A full-featured Model Context Protocol (MCP) server for controlling Bitwig Studio via the DrivenByMoss OSC extension. Exposes 204 MCP tools covering every OSC command DrivenByMoss supports — transport, tracks, devices, clips, scenes, browser, project, layout, MIDI, and more.
Table of Contents
- Prerequisites
- Installation
- DrivenByMoss OSC Setup
- Configuration
- Running the Server
- Registering with Claude Code
- Architecture
- Tool Reference
- Usage Examples
- Troubleshooting
Prerequisites
- Bitwig Studio 4.x or later
- DrivenByMoss installed as a Bitwig controller extension (download)
- Python 3.10+
Installation
# Clone or navigate to the project
cd bitwig-mcp
# Create a virtual environment
python -m venv .venv
# Activate it (Windows)
.venv\Scripts\activate
# Install the package and all dependencies
pip install -e .
Dependencies installed:
mcp[cli]— Model Context Protocol SDK (FastMCP server)python-osc— OSC send/receive over UDP
DrivenByMoss OSC Setup
- Open Bitwig Studio → Preferences → Controllers
- Click Add controller → search for DrivenByMoss → select Open Sound Control (OSC)
- Configure the OSC extension settings:
| DrivenByMoss Setting | Value | Meaning |
|---|---|---|
| Port to receive on | 8000 |
DrivenByMoss listens here — bitwig-mcp sends to this port |
| Host to send to | 127.0.0.1 |
Where DrivenByMoss sends state updates |
| Port to send to | 9000 |
DrivenByMoss sends here — bitwig-mcp listens on this port |
- Enable the controller and restart Bitwig if prompted.
Important: "Port to receive on" is where DrivenByMoss accepts commands (bitwig-mcp sends TO it). "Port to send to" is where DrivenByMoss pushes state updates (bitwig-mcp listens ON it). These are from DrivenByMoss's perspective — the opposite of what you might expect.
Configuration
All settings are controlled via environment variables with sensible defaults:
| Variable | Default | Description |
|---|---|---|
BITWIG_HOST |
127.0.0.1 |
Host where Bitwig is running |
BITWIG_SEND_PORT |
8000 |
Port to send OSC commands to (DrivenByMoss receive port) |
BITWIG_RECEIVE_PORT |
9000 |
Port to listen for state updates on (DrivenByMoss send port) |
BITWIG_TIMEOUT |
5.0 |
Seconds to wait when using wait_for_state() |
BITWIG_REFRESH_WAIT |
0.5 |
Seconds to wait after sending /refresh for state to populate |
Example — connecting to Bitwig on another machine:
BITWIG_HOST=192.168.1.10 BITWIG_SEND_PORT=8000 bitwig-mcp
Running the Server
# With venv activated
bitwig-mcp
# Or directly via the venv executable (Windows)
.venv\Scripts\bitwig-mcp.exe
# Or via Python
python -m bitwig_mcp.server
The server starts and listens for MCP connections on stdio (standard MCP transport). It also starts the OSC listener thread in the background immediately.
Registering with Claude Code
Global (available in all sessions)
claude mcp add bitwig-mcp "C:\path\to\bitwig-mcp\.venv\Scripts\bitwig-mcp.exe"
Project-scoped (.claude/settings.json)
{
"mcpServers": {
"bitwig-mcp": {
"command": "C:\\path\\to\\bitwig-mcp\\.venv\\Scripts\\bitwig-mcp.exe",
"args": []
}
}
}
Verify it's working
Once registered, ask Claude:
"Check if Bitwig is connected" → calls
ping_bitwig"Get the current transport state" → callstransport_get_state
Architecture
Push-Based OSC Protocol
DrivenByMoss uses a push-based (publish-subscribe) model rather than request/response. Bitwig proactively sends OSC messages to notify about every state change. This means:
- No polling needed — state arrives automatically when anything changes in Bitwig
- State store —
osc_client.pymaintains an in-memory dict (address → last received args) updated by every incoming OSC message /refresh— sending this special command triggers Bitwig to dump its full current state immediately (used on startup and byrefresh_state)
Data Flow
Claude / LLM
│
│ MCP tool calls
▼
bitwig-mcp (FastMCP server)
│ ▲
│ cmd(addr, *args) │ OSC state updates
│ (UDP to port 8000) │ (UDP from port 9000)
▼ │
DrivenByMoss OSC extension (inside Bitwig Studio)
│ ▲
│ Bitwig Java API │
▼ │
Bitwig Studio ──────────┘
Key Components
| File | Purpose |
|---|---|
src/bitwig_mcp/server.py |
FastMCP server entry point; registers all tool modules |
src/bitwig_mcp/config.py |
Environment variable configuration |
src/bitwig_mcp/osc_client.py |
Thread-safe OSC singleton: send, receive, state store |
src/bitwig_mcp/tools/ |
One file per domain, each exports register(mcp) |
OSC Client API
from bitwig_mcp.osc_client import get_client
c = get_client()
# Send a command to Bitwig (fire-and-forget)
c.cmd("/play", 1)
c.cmd("/track/1/volume", 100)
# Read cached state (returns tuple or None)
state = c.get_state("/tempo/raw") # e.g. (128.0,)
value = c.get_state_value("/play") # e.g. 1
# Wait for a state update (blocks up to timeout)
c.wait_for_state("/track/1/volume", timeout=2.0)
# Trigger full state dump from Bitwig
c.refresh()
# Get all known state as a dict
all_state = c.get_all_state()
# Check connection
connected = c.ping()
Value Ranges
DrivenByMoss uses the following conventions (default resolution: 128 steps):
| Parameter | Range | Notes |
|---|---|---|
| Volume | 0–127 |
~100 = unity gain (0 dB) |
| Pan | 0–127 |
64 = center |
| Send volume | 0–127 |
~100 = unity |
| Boolean (on/off) | 0 or 1 |
Omitting triggers a toggle |
| Normalized floats | 0.0–1.0 |
Device parameters, EQ settings |
| MIDI note | 0–127 |
60 = C4 (middle C) |
| MIDI velocity | 0–127 |
0 = note off |
| Track/clip indices | 1–8 |
1-indexed in OSC paths |
| Colors | "rgb(r,g,b)" |
e.g. "rgb(255,128,0)" |
Tool Reference
Transport
Tools for controlling playback, recording, tempo, loop, and automation.
| Tool | Parameters | Description |
|---|---|---|
transport_play |
value=1 |
Start/stop playback. 1 = play, 0 = stop |
transport_stop |
— | Stop playback (rewinds if already stopped) |
transport_restart |
— | Restart playback from the beginning |
transport_toggle_record |
value? |
Toggle/set arranger record mode |
transport_toggle_overdub |
value? |
Toggle/set arranger overdub |
transport_toggle_launcher_overdub |
value? |
Toggle/set clip launcher overdub |
transport_toggle_loop |
value? |
Toggle/set loop (repeat) mode |
transport_toggle_punch_in |
value? |
Toggle/set punch-in recording |
transport_toggle_punch_out |
value? |
Toggle/set punch-out recording |
transport_toggle_click |
value? |
Toggle/set metronome |
transport_set_click_volume |
value (0–100) |
Set metronome volume |
transport_toggle_click_ticks |
value? |
Toggle/set metronome tick marks |
transport_toggle_click_preroll |
value? |
Toggle/set pre-roll click |
transport_quantize |
— | Quantize the cursor clip |
transport_set_tempo |
bpm (float) |
Set tempo in BPM |
transport_tap_tempo |
— | Tap tempo (call repeatedly) |
transport_adjust_tempo |
amount, direction ("+"/"-") |
Nudge tempo up or down |
transport_set_position |
value (float) |
Set timeline position in beats |
transport_step_position |
direction ("+"/"-"), size ("small"/"large") |
Step position forward/backward |
transport_goto_start |
— | Jump to beginning of arrangement |
transport_set_crossfade |
value (0–127) |
Set crossfader position (64 = center) |
transport_reset_crossfade |
— | Reset crossfader to center |
transport_toggle_autowrite |
value? |
Toggle/set arranger automation write |
transport_toggle_launcher_autowrite |
value? |
Toggle/set launcher automation write |
transport_set_automation_mode |
mode ("OFF"/"LATCH"/"TOUCH") |
Set automation write mode |
transport_set_preroll |
measures (int) |
Set pre-roll measure count |
transport_set_post_recording_action |
action (string) |
Set launcher post-recording action |
transport_set_post_recording_offset |
beats (float) |
Set post-recording time offset in beats |
transport_set_launch_quantization |
quantization (string) |
Set default clip launch quantization |
transport_get_state |
— | Get complete transport state snapshot |
Post-recording action values: "OFF", "PLAY_RECORDED", "RECORD_NEXT_FREE_SLOT", "STOP", "RETURN_TO_ARRANGEMENT"
Launch quantization values: "NONE", "1/32", "1/16", "1/8", "1/4", "1/2", "1", "2", "4", "8"
Track
Tools for mixer controls, clips, sends, and navigation across the 8-track bank window. All track_index parameters are 1-indexed (1–8).
| Tool | Parameters | Description |
|---|---|---|
track_set_volume |
track_index, value (0–127) |
Set track volume |
track_reset_volume |
track_index |
Reset volume to unity gain |
track_set_pan |
track_index, value (0–127) |
Set track pan (64 = center) |
track_reset_pan |
track_index |
Reset pan to center |
track_toggle_mute |
track_index, value? |
Toggle/set mute |
track_toggle_solo |
track_index, value? |
Toggle/set solo |
track_toggle_recarm |
track_index, value? |
Toggle/set record arm |
track_toggle_monitor |
track_index, value? |
Toggle/set input monitoring |
track_toggle_auto_monitor |
track_index, value? |
Toggle/set auto-monitoring |
track_select |
track_index |
Select/focus a track |
track_set_crossfade_mode |
track_index, mode ("A"/"B"/"AB") |
Set crossfade assignment |
track_set_send_volume |
track_index, send_index, value (0–127) |
Set a send level |
track_reset_send_volume |
track_index, send_index |
Reset send to default |
track_toggle_send |
track_index, send_index, value? |
Toggle/set send active |
track_clip_launch |
track_index, clip_index |
Launch a clip slot |
track_clip_launch_alt |
track_index, clip_index |
Launch clip (alternative mode) |
track_clip_record |
track_index, clip_index |
Record into a clip slot |
track_clip_create |
track_index, clip_index, length_beats=4.0 |
Create empty clip |
track_clip_duplicate |
track_index, clip_index |
Duplicate a clip |
track_clip_remove |
track_index, clip_index |
Delete a clip |
track_clip_set_name |
track_index, clip_index, name |
Rename a clip |
track_clip_set_color |
track_index, clip_index, color |
Set clip color (rgb string) |
track_navigate_next |
— | Select next track |
track_navigate_prev |
— | Select previous track |
track_bank_next |
— | Scroll track bank forward one page |
track_bank_prev |
— | Scroll track bank backward one page |
track_navigate_parent |
— | Navigate to parent group track |
track_enter_group |
track_index |
Enter a group track |
track_add_audio |
— | Add a new audio track |
track_add_instrument |
— | Add a new instrument track |
track_add_effect |
— | Add a new effect/FX track |
track_stop_clips |
track_index |
Stop all clips on a track |
track_toggle_bank |
— | Toggle between main and effect track bank |
track_set_param |
param_index (1–8), value (0.0–1.0) |
Set a remote control parameter |
track_reset_param |
param_index |
Reset remote control parameter |
track_navigate_params |
direction ("+"/"-"/"page+"/"page-") |
Navigate remote control parameters |
track_indicate_volume |
all_tracks=True |
Enable volume indication |
track_indicate_pan |
all_tracks=True |
Enable pan indication |
track_indicate_send |
send_index |
Enable send indication |
track_toggle_vu_meters |
value? |
Toggle/set VU meter feedback |
track_get_info |
track_index |
Get full state for one track |
track_get_all |
— | Get state for all 8 tracks in bank |
track_selected_get_state |
— | Get cursor (selected) track state |
track_selected_set_volume |
value (0–127) |
Set cursor track volume |
track_selected_set_pan |
value (0–127) |
Set cursor track pan |
track_selected_toggle_mute |
value? |
Toggle/set cursor track mute |
track_selected_toggle_solo |
value? |
Toggle/set cursor track solo |
track_selected_toggle_recarm |
value? |
Toggle/set cursor track record arm |
Master Track
| Tool | Parameters | Description |
|---|---|---|
master_set_volume |
value (0–127) |
Set master track volume |
master_reset_volume |
— | Reset master volume to unity |
master_set_pan |
value (0–127) |
Set master track pan |
master_reset_pan |
— | Reset master pan to center |
master_toggle_mute |
value? |
Toggle/set master mute |
master_select |
— | Select/focus the master track |
master_get_state |
— | Get complete master track state |
Device
Tools for the cursor device (the currently focused device in Bitwig's device chain). Also covers the primary instrument (primary_*) and EQ device (eq_*).
| Tool | Parameters | Description |
|---|---|---|
device_toggle_bypass |
value? |
Toggle/set device bypass |
device_toggle_expand |
value? |
Toggle/set device expanded view |
device_toggle_parameters |
value? |
Toggle/set parameters panel |
device_toggle_window |
value? |
Toggle/set plugin window |
device_toggle_pinned |
value? |
Toggle/set cursor pin |
device_navigate_next |
— | Move cursor to next device in chain |
device_navigate_prev |
— | Move cursor to previous device |
device_set_param |
param_index (1–8), value (0.0–1.0) |
Set device parameter |
device_reset_param |
param_index |
Reset parameter to default |
device_navigate_params |
direction ("+"/"-"/"page+"/"page-") |
Navigate parameter pages |
device_select_page |
page_index |
Select a parameter page |
device_select_sibling |
sibling_index |
Select a sibling device in chain |
device_layer_select |
layer_index |
Select a device layer |
device_layer_set_volume |
layer_index, value (0–127) |
Set layer volume |
device_layer_set_pan |
layer_index, value (0–127) |
Set layer pan |
device_layer_toggle_mute |
layer_index, value? |
Toggle/set layer mute |
device_layer_set_send_volume |
layer_index, send_index, value (0–127) |
Set layer send volume |
device_layer_enter |
layer_index |
Enter a layer to view its devices |
device_layer_navigate |
direction ("+"/"-"/"page+"/"page-") |
Navigate layers |
device_drumpad_select |
pad_index |
Select a drum pad |
device_drumpad_set_volume |
pad_index, value (0–127) |
Set drum pad volume |
device_drumpad_set_pan |
pad_index, value (0–127) |
Set drum pad pan |
device_drumpad_toggle_mute |
pad_index, value? |
Toggle/set drum pad mute |
device_drumpad_toggle_solo |
pad_index, value? |
Toggle/set drum pad solo |
primary_set_param |
param_index (1–8), value (0.0–1.0) |
Set primary instrument parameter |
primary_toggle_bypass |
value? |
Toggle/set primary instrument bypass |
primary_navigate_params |
direction ("+"/"-"/"page+"/"page-") |
Navigate primary instrument params |
eq_set_type |
band_index, eq_type (string) |
Set EQ band filter type |
eq_set_gain |
band_index, value (0.0–1.0) |
Set EQ band gain |
eq_set_frequency |
band_index, value (0.0–1.0) |
Set EQ band frequency (normalized) |
eq_set_q |
band_index, value (0.0–1.0) |
Set EQ band Q factor (normalized) |
eq_add |
— | Add an EQ+ device to the selected track |
device_get_state |
— | Get full device state (params, pages, layers, siblings) |
EQ band types: "OFF", "LP1", "LP2", "HP1", "HP2", "LS" (low shelf), "HS" (high shelf), "BELL", "NOTCH"
Clip
Tools for the cursor clip — the clip currently in focus in Bitwig's clip editor.
| Tool | Parameters | Description |
|---|---|---|
clip_quantize |
— | Quantize the cursor clip |
clip_set_name |
name |
Rename the cursor clip |
clip_set_color |
color (rgb string) |
Set cursor clip color |
clip_toggle_pinned |
value? |
Toggle/set clip pin (keeps focus on this clip) |
clip_launch |
— | Launch the cursor clip |
clip_launch_alt |
— | Launch cursor clip (alternative mode) |
clip_record |
— | Record into the cursor clip |
clip_create |
length_beats=4.0 |
Create a new empty clip |
clip_stop |
— | Stop clips on the cursor track |
clip_stop_alt |
— | Stop clips (alternative mode) |
clip_stop_all |
— | Stop all playing clips globally |
clip_stop_all_alt |
— | Stop all clips (alternative mode) |
clip_navigate |
direction ("+"/"-") |
Navigate to next/previous clip |
clip_get_state |
— | Get cursor clip state (name, color, pinned) |
Scene
Tools for the clip launcher scene bank. All scene_index parameters are 1-indexed.
| Tool | Parameters | Description |
|---|---|---|
scene_launch |
scene_index |
Launch a scene (triggers all clips in that row) |
scene_launch_alt |
scene_index |
Launch scene (alternative mode) |
scene_select |
scene_index |
Select a scene |
scene_duplicate |
scene_index |
Duplicate a scene |
scene_remove |
scene_index |
Delete a scene |
scene_set_name |
scene_index, name |
Rename a scene |
scene_set_color |
scene_index, color (rgb string) |
Set scene color |
scene_navigate |
direction ("+"/"-"/"bank+"/"bank-") |
Scroll scene bank |
scene_add |
— | Add a new empty scene |
scene_create_from_playing |
— | Create scene from all currently playing clips |
scene_get_all |
— | Get state of all 8 scenes in current bank |
Browser
Tools for navigating Bitwig's content browser (presets, devices, samples).
| Tool | Parameters | Description |
|---|---|---|
browser_open_preset |
— | Open browser to replace current device with a preset |
browser_insert_device_after |
— | Open browser to insert device after cursor |
browser_insert_device_before |
— | Open browser to insert device before cursor |
browser_navigate_tab |
direction ("+"/"-") |
Navigate content type tabs |
browser_navigate_filter |
column_index, direction ("+"/"-") |
Navigate a filter column |
browser_reset_filter |
column_index |
Reset a filter column to show all |
browser_navigate_results |
direction ("+"/"-") |
Navigate results list |
browser_commit |
— | Load the selected browser item |
browser_cancel |
— | Close browser without loading |
browser_get_state |
— | Get browser state (tab, filters, results) |
Project
| Tool | Parameters | Description |
|---|---|---|
project_save |
— | Save the current project |
project_navigate |
direction ("+"/"-") |
Switch between open projects |
project_toggle_engine |
value? |
Toggle/set the Bitwig audio engine |
project_set_param |
param_index (1–8), value (0.0–1.0) |
Set a project remote control parameter |
project_reset_param |
param_index |
Reset project parameter to default |
project_navigate_params |
direction ("+"/"-"/"page+"/"page-") |
Navigate project parameters |
project_select_page |
page_index |
Select a project parameter page |
project_get_state |
— | Get project state (name, engine, params, pages) |
Layout & Panels
Tools for controlling Bitwig's UI layout and panel visibility.
| Tool | Parameters | Description |
|---|---|---|
layout_set |
layout_name |
Set the panel layout (e.g. "SINGLE", "DOUBLE", "THREE") |
panel_toggle_note_editor |
value? |
Toggle/set note editor panel |
panel_toggle_automation_editor |
value? |
Toggle/set automation editor panel |
panel_toggle_devices |
value? |
Toggle/set devices panel |
panel_toggle_mixer |
value? |
Toggle/set mixer panel |
panel_toggle_fullscreen |
value? |
Toggle/set fullscreen mode |
arranger_toggle_cue_markers |
value? |
Toggle cue marker visibility in arranger |
arranger_toggle_playback_follow |
value? |
Toggle playback follow (auto-scroll) |
arranger_toggle_track_height |
value? |
Toggle double track row height |
arranger_toggle_clip_launcher |
value? |
Toggle clip launcher section in arranger |
arranger_toggle_timeline |
value? |
Toggle timeline visibility |
arranger_toggle_io_section |
value? |
Toggle I/O section in arranger |
arranger_toggle_effect_tracks |
value? |
Toggle effect tracks visibility |
mixer_toggle_clip_launcher |
value? |
Toggle clip launcher in mixer |
mixer_toggle_crossfade_section |
value? |
Toggle crossfade section in mixer |
mixer_toggle_device_section |
value? |
Toggle device section in mixer |
mixer_toggle_sends_section |
value? |
Toggle sends section in mixer |
mixer_toggle_io_section |
value? |
Toggle I/O section in mixer |
mixer_toggle_meter_section |
value? |
Toggle meter/VU section in mixer |
layout_get_state |
— | Get full layout and visibility state |
MIDI (Virtual Keyboard)
Tools for sending MIDI messages through DrivenByMoss's virtual keyboard. Channels are 1-indexed (1–16).
| Tool | Parameters | Description |
|---|---|---|
midi_note |
channel, note (0–127), velocity (0–127) |
Send a note on/off message |
midi_note_with_array |
channel, note, velocity |
Send note using array format |
midi_note_octave |
channel, direction ("+"/"-") |
Shift note keyboard octave |
midi_drum |
channel, note (0–127), velocity (0–127) |
Send a drum pad note |
midi_drum_octave |
channel, direction ("+"/"-") |
Shift drum pad octave |
midi_cc |
channel, cc (0–127), value (0–127) |
Send a MIDI CC message |
midi_channel_aftertouch |
channel, pressure (0–127) |
Send channel aftertouch |
midi_poly_aftertouch |
channel, note (0–127), pressure (0–127) |
Send polyphonic aftertouch |
midi_pitchbend |
channel, value (0–127) |
Send pitch bend (64 = center) |
midi_set_fixed_velocity |
velocity (0–127) |
Set fixed accent velocity (0 = disable) |
midi_note_repeat_toggle |
value? |
Toggle/set note repeat mode |
midi_note_repeat_period |
period (string) |
Set note repeat period (e.g. "1/16") |
midi_note_repeat_length |
length (string) |
Set note repeat length (e.g. "1/16") |
midi_get_state |
— | Get MIDI/note repeat state |
Note repeat period/length values: "1/32", "1/16", "1/8T", "1/8", "1/4T", "1/4", "1/2", "1"
Miscellaneous
| Tool | Parameters | Description |
|---|---|---|
undo |
— | Undo the last action |
redo |
— | Redo the last undone action |
action_execute |
action_index (1–20) |
Execute a DrivenByMoss assignable custom action |
marker_launch |
marker_index |
Jump to and play from a cue marker |
marker_navigate |
direction ("bank+"/"bank-") |
Navigate marker bank pages |
marker_get_all |
— | Get all markers in current bank |
refresh_state |
— | Send /refresh and return full state dump |
state_dump |
— | Return current state store without refreshing |
ping_bitwig |
— | Check if Bitwig+DrivenByMoss is reachable |
Usage Examples
Check connection and get initial state
ping_bitwig
→ {"connected": true, "message": "Bitwig + DrivenByMoss OSC is active"}
refresh_state
→ {"/play": (0,), "/tempo/raw": (128.0,), "/track/1/name": ("Drums",), ...}
Transport control
transport_set_tempo(bpm=120.0)
transport_toggle_loop(value=1)
transport_play()
transport_get_state()
→ {"playing": 1, "tempo_bpm": 120.0, "loop": 1, ...}
transport_stop()
Mixing
track_get_all()
→ [{"index": 1, "name": "Drums", "volume": 100, "mute": 0, ...}, ...]
track_set_volume(track_index=1, value=90)
track_toggle_mute(track_index=2)
track_toggle_solo(track_index=1)
master_set_volume(value=110)
Launching clips and scenes
scene_get_all()
→ [{"index": 1, "name": "Verse", ...}, {"index": 2, "name": "Chorus", ...}]
scene_launch(scene_index=2)
track_clip_launch(track_index=3, clip_index=1)
clip_stop_all()
Device control
device_get_state()
→ {"name": "Polysynth", "bypass": 0, "params": [...], "pages": [...]}
device_set_param(param_index=1, value=0.75)
device_select_page(page_index=2)
device_toggle_bypass()
MIDI input
# Play a C major chord on channel 1
midi_note(channel=1, note=60, velocity=100) # C4
midi_note(channel=1, note=64, velocity=100) # E4
midi_note(channel=1, note=67, velocity=100) # G4
# Release
midi_note(channel=1, note=60, velocity=0)
midi_note(channel=1, note=64, velocity=0)
midi_note(channel=1, note=67, velocity=0)
# Drum hit on pad 1 (usually kick drum)
midi_drum(channel=10, note=36, velocity=127)
Browser
browser_open_preset() # Opens browser for current device
browser_navigate_tab("+") # Switch to next content type
browser_navigate_results("+") # Move to next result
browser_commit() # Load the selection
Troubleshooting
ping_bitwig returns connected: false
- Is Bitwig running? Make sure Bitwig Studio is open and a project is loaded.
- Is DrivenByMoss active? Go to Preferences → Controllers and confirm the OSC controller is enabled (green checkmark).
- Check ports: DrivenByMoss "receive port" must be
8000and "send to port" must be9000(or setBITWIG_SEND_PORT/BITWIG_RECEIVE_PORTto match your custom values). - Firewall: Ensure UDP ports 8000 and 9000 are not blocked by a firewall.
- Port conflict: Check nothing else is using those ports:
netstat -ano | findstr :8000(Windows).
State values all return None
The state store is empty, meaning no messages have been received from Bitwig. Call refresh_state to trigger a full dump:
refresh_state()
If it still returns mostly empty, see the connectivity steps above.
track_get_all shows only 8 tracks but I have more
DrivenByMoss uses a track bank window of 8 tracks. Use track_bank_next / track_bank_prev to scroll to other groups of tracks.
Changes not reflected in state after a command
DrivenByMoss sends state updates asynchronously. For fast sequences of commands, wait briefly or call refresh_state to re-sync. The BITWIG_REFRESH_WAIT env var controls how long refresh() waits (default 0.5 s).
Server exits immediately
Make sure you are running the server directly, not piping to it. The MCP server communicates over stdio — it is meant to be launched by a MCP client (like Claude Code), not run interactively in a terminal. To test it manually, use the MCP Inspector.
License
MIT