reaper-mcp-bridge
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@reaper-mcp-bridge Create a track called Drums and color it dark red"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
reaper-mcp-bridge
Control REAPER from AI agents — Claude (Desktop / Code), Codex, or any MCP-capable client. Build projects, manage tracks, record and edit, write MIDI, mix, render, batch-rename/export — by talking to your agent in plain language.
Claude / Codex / any MCP client
│ MCP (stdio, JSON-RPC) — agent spawns the server as a subprocess
▼
Python MCP server (this package)
│ file IPC: writes <id>.req.json / reads <id>.res.json
▼
Lua bridge script (resident inside REAPER via reaper.defer)
│ ReaScript API
▼
REAPERDesign highlights:
No extra moving parts — no reapy, no network ports, no firewall prompts. The Python server and REAPER talk through JSON files in a directory.
Two layers of tools:
~50 typed, discoverable, undo-friendly tools (tracks / editing / MIDI / mixing / rendering / batch);
reaper_evalas an escape hatch — the agent can run arbitrary Lua inside REAPER for anything not covered.
Undoable — every mutating tool is wrapped in a single REAPER undo block. Ctrl+Z works, and tool names show up in REAPER's undo history.
Quick start
Prerequisites:
REAPER
uv (
winget install astral-sh.uv/brew install uv). uv fetches a suitable Python and the dependencies on its own, so no separate Python install is needed.Git, which uv uses to download this repository. No Git? See Install without Git.
1. Install the package (once)
uv tool install git+https://github.com/Echo722/reaper-mcp-bridgeThis puts a reaper-mcp-bridge command on your PATH. Your agent starts it locally, so it keeps working without network access. If the command isn't found afterwards, run uv tool update-shell and open a new terminal.
2. Install the Lua bridge into REAPER (once)
reaper-mcp-bridge install-bridge --autostartThis auto-detects your REAPER install (portable installs: add --reaper-dir "D:\REAPER"), copies the bridge script into REAPER's Scripts/ folder, and wires it to load on startup. Restart REAPER; its console should show:
[MCP] bridge listening @ <...>/Scripts/reaper_mcp_bridge_dataVerify end-to-end:
reaper-mcp-bridge doctor3. Register the server with your agent (once per client)
Claude Code
claude mcp add --scope user reaper -- reaper-mcp-bridgeClaude Desktop — merge examples/claude_desktop_config.example.json into your claude_desktop_config.json, then fully quit and relaunch Claude Desktop.
Codex CLI — add to ~/.codex/config.toml (see examples/codex_config.example.toml):
[mcp_servers.reaper]
command = "reaper-mcp-bridge"Any other MCP client that supports stdio servers works the same way: the command is reaper-mcp-bridge, with no arguments. If a client can't find it, give it the full path; uv tool dir --bin prints the folder it lives in.
4. Use it
Open REAPER, then ask your agent things like:
"Look at the current project: list all tracks and describe the structure."
"Create a track called Drums and color it dark red."
"Insert a 4-bar C–Am–F–G progression on track 0, one chord per bar."
"Rename all regions to
Take_$numstarting from 01.""Export every region to
D:\bounces\session1\, named after the region."
Related MCP server: reaper-mcp
Updating
uv tool upgrade reaper-mcp-bridgeThen restart your agent (or reconnect the reaper server) so it starts the new version.
Install without Git
Install from GitHub's zip download of the main branch instead:
uv tool install https://github.com/Echo722/reaper-mcp-bridge/archive/refs/heads/main.zipTo update, run the same command with --reinstall added. Everything else in Quick start stays the same.
Tool overview
Domain | Tools |
Diagnostics |
|
Project |
|
Tracks |
|
Record / edit |
|
MIDI |
|
Mixing |
|
Render |
|
Batch |
|
reaper_eval covers anything else via the ReaScript API.
Security
reaper_eval is arbitrary code execution on your machine. The Lua environment inside REAPER has full access to os, io, etc. — any agent allowed to call this server can, in principle, run any command as you. This is by design (it is the escape hatch that makes the tool set complete), and it is fine for the intended use: a trusted, local agent you operate yourself. Do not expose this server to untrusted clients, and review your agent's tool-permission settings if you want a human in the loop for reaper_eval.
Concurrency
Multiple agents can be registered (and even connected) at the same time — each spawns its own server process, and requests never collide thanks to per-request IDs. However, the tools are not coordinated across agents: two agents editing the same project simultaneously will interleave undo entries and stomp on each other's selections. Recommended usage: let one agent work at a time.
Custom bridge directory
By default the bridge data dir lives at <REAPER resource path>/Scripts/reaper_mcp_bridge_data, and install-bridge records its location so the Python side finds it automatically (env REAPER_MCP_BRIDGE_DIR > locator file > platform default). To relocate it, set REAPER_MCP_BRIDGE_DIR in both the environment REAPER starts from and the env block of your MCP client config.
Troubleshooting
"timeout waiting for bridge response" — REAPER isn't open, or the bridge script isn't running. Run
reaper-mcp-bridge doctor.No
[MCP] bridge listeningline in REAPER's console — re-runreaper-mcp-bridge install-bridge --autostartand restart REAPER, or loadScripts/reaper_mcp_bridge.luamanually via the Actions list.REAPER is open but the bridge never starts — a startup dialog (e.g. "Choose Project" / crash recovery) blocks
__startup.luauntil dismissed. Close the dialog; the bridge loads right after.Doctor says the dir exists but ping fails — make sure the dir REAPER prints in its console matches the one doctor prints.
Development
git clone https://github.com/Echo722/reaper-mcp-bridge && cd reaper-mcp-bridge
uv run reaper-mcp-bridge doctor # uv creates the env on first run
uv run --with pytest pytest # unit tests (no REAPER needed)
uv run python tests/e2e_ping.py # end-to-end (REAPER + bridge running)Repo layout:
server/
app.py # FastMCP entry point (tool registration)
cli.py # console entry: serve / install-bridge / doctor
installer.py # cross-platform Lua bridge installer
bridge_client.py # file IPC client + bridge dir resolution
bridge_lua/ # the Lua side (shipped as package data)
tools/ # typed tools by domain
examples/ # MCP client config templates
tests/License
MIT. server/bridge_lua/json.lua is rxi/json.lua (MIT, copyright header retained in file).
Available Tools
50 toolsadd_fxA
Add an FX plugin to a track. fx_name is matched the way REAPER's FX browser matches: e.g. 'ReaEQ', 'VST:Pro-Q 3', 'ReaComp'. Returns the new FX index on that track, or -1 if not found.
Inputs: fx_name (required), track_index (required).
add_trackA
Add a new track. name is optional. position is the 0-based index where to insert; -1 (default) appends at the end. Returns {index, name}.
Inputs: name, position.
apply_templateA
Build a track layout from a template. tracks is a list, processed in order. Each entry may contain: {name, color:[r,g,b]?, volume_db?, pan?, folder_start?:bool, folder_end?:int (1=close one, 2=close two, ...), record_armed?:bool, record_input?:int, fx?:[name,name,...]}. Appends to the current project; does not clear existing tracks. Returns the indices and names of the new tracks.
Inputs: tracks (required).
batch_export_regionsB
Render every region in the project to its own file. Uses the project's currently-configured render FORMAT (configure it once in REAPER's Render dialog, then this just changes bounds + output dir + pattern). file_name_pattern supports REAPER wildcards: default '$region' = filename equals region name.
Inputs: output_dir (required), only_matching, file_name_pattern.
batch_rename_itemsA
Rename items on a track in order. pattern supports tokens: $num (1-based, zero-padded to pad_width), $idx (1-based, no padding), $name (original active-take name), $track (track name). If track_index = -1, applies across ALL tracks in track-then-position order. Returns the list of renames applied.
Inputs: pattern (required), pad_width, start_num, track_index.
batch_rename_regionsB
Rename ALL regions in the project in time order. Pattern tokens: $num (1-based, zero-padded to pad_width), $idx, $name (original name).
Inputs: pattern (required), pad_width, start_num.
bridge_statusA
Print the bridge directory the Python side is using. Useful when diagnosing setup issues (it must match the Lua side).
Inputs: no named parameters.
clear_time_selectionC
Clear the time selection.
Inputs: no named parameters.
create_chord_progressionA
Convenience: build a chord progression on a track from scratch. Creates a MIDI item and writes one chord per entry. chords: [{root: 0..11 (C=0), type: 'maj'|'min'|'7'|'maj7'|'min7'|'dim'|'aug', duration_qn: float, octave?: int (default 4)}]. Notes are placed back-to-back starting at item start (start_sec).
Inputs: chords (required), start_sec (required), track_index (required).
delete_trackC
Delete a track by 0-based index.
Inputs: index (required).
get_project_infoA
Get an overview of the current REAPER project: file path, sample rate, length in seconds, play state, track count, region count, marker count, time selection. Call this first to orient yourself.
Inputs: no named parameters.
get_render_settingsA
Get the current render settings: bounds flag, output file/dir, pattern, sample rate, channels.
Inputs: no named parameters.
glue_selected_itemsA
Glue (consolidate) currently selected items. Each contiguous group on a track becomes one item. Useful after a lot of editing.
Inputs: no named parameters.
insert_midi_itemB
Insert an empty MIDI item on a track, spanning [start_sec, end_sec]. Returns the item index on the track.
Inputs: end_sec (required), start_sec (required), track_index (required).
insert_midi_notesA
Insert MIDI notes into an existing MIDI item. Each note: {pitch: 0..127, start_qn: float, length_qn: float, velocity?: 1..127 (default 96), channel?: 0..15 (default 0)}. Positions are quarter-notes relative to the item start.
Inputs: notes (required), item_index (required), track_index (required).
list_fxA
List FX on a track with their parameters. Each entry: {index, name, enabled, num_params, params: [{index, name, value, value_normalized, min, max}]}. Set include_params=false to skip parameter details (faster).
Inputs: track_index (required), include_params. Returns: result
list_markersA
List all markers (not regions): {enum_index, index, name, time_sec, color_rgb}.
Inputs: no named parameters. Returns: result
list_regionsB
List all regions in the project: {index, name, start_sec, end_sec, color_rgb}.
Inputs: no named parameters. Returns: result
list_tracksA
List all tracks with index, name, volume (dB), pan (-1..1), mute, solo, record arm, color (RGB or 0 if none), item count, FX names.
Inputs: no named parameters. Returns: result
move_selected_itemsB
Shift the position of all currently selected items by delta_sec seconds.
Inputs: delta_sec (required).
new_projectA
Create a brand-new empty project in a new tab and switch to it. Does NOT save the previous project.
Inputs: no named parameters.
normalize_loudnessA
Normalize the perceived loudness of items by adjusting each item's volume (D_VOL). Doesn't modify audio data. target_db: e.g. -14 for streaming, -23 for broadcast EBU R128. kind: 'LUFS-I' (default), 'RMS-I', 'peak', 'true_peak', 'LUFS-M_max', 'LUFS-S_max'. selected_only: true = only currently selected items; false = every item in the project. Requires REAPER 6.40+.
Inputs: kind, target_db, selected_only.
pingA
Health check: confirm the REAPER bridge is running. Returns {pong: true, time: } on success.
Inputs: no named parameters.
playA
Start playback from the edit cursor.
Inputs: no named parameters.
quantize_midi_itemA
Quantize note positions in the active MIDI take of the item at (track_index, item_index) to grid_qn quarter notes. Pass 0.25 for 16th-note grid, 0.5 for 8ths, 1.0 for quarters.
Inputs: grid_qn (required), item_index (required), track_index (required).
reaper_evalA
Execute arbitrary Lua inside REAPER. The reaper global is available; values you return are sent back as JSON. Use this for anything not covered by a typed tool. Example: return reaper.GetNumTracks(). If you pass args, it is exposed in the chunk as the variable args.
Inputs: code (required), args, undo, label.
recordB
Start recording on all armed tracks.
Inputs: no named parameters.
remove_fxB
Remove an FX from a track by FX index.
Inputs: fx_index (required), track_index (required).
rename_trackC
Rename a track.
Inputs: name (required), index (required).
renderA
Render to a directory with the given bounds and file pattern. bounds ∈ {'entire_project','time_selection','all_regions','selected_items','selected_regions'}. file_name_pattern uses REAPER's wildcards: e.g. '$project', '$region', '$track', '$item'. Extension comes from current render format (configure via REAPER once, or call render_with_current_settings).
Inputs: output_dir (required), bounds, sample_rate, file_name_pattern.
render_with_current_settingsA
Trigger a render using REAPER's current render-dialog settings (non-interactive — no UI popup). Useful if the user has already configured the render dialog.
Inputs: no named parameters.
save_project_asB
Save the current project to a specific path (.rpp). Creates parent dirs if needed.
Inputs: path (required).
select_items_on_trackA
Select items on a track by index range. Pass start=-1, end=-1 to select all items on the track. replace = clear other selections first.
Inputs: track_index (required), replace, end_item, start_item.
select_tracksA
Select tracks by index list (replacing any previous selection). Pass [] to clear selection.
Inputs: indices (required).
set_cursorC
Move the edit cursor to time_sec.
Inputs: time_sec (required).
set_fx_enabledC
Bypass / enable an FX on a track.
Inputs: enabled (required), fx_index (required), track_index (required).
set_fx_paramB
Set an FX parameter. normalized=true (default) means value is in 0..1. Set normalized=false to use the plugin's native units.
Inputs: value (required), fx_index (required), param_index (required), track_index (required), +1 more.
set_master_volume_dbB
Set master track volume in dB. 0 = unity.
Inputs: db (required).
set_record_inputB
Set the record input for a track. input is REAPER's input index: 0..N-1 for mono inputs, or use 1024+ch for stereo pair starting at ch. Pass -1 to set to MIDI all-channels-all-devices.
Inputs: input (required), track_index (required).
set_selected_item_fadesA
Set fade-in and fade-out (seconds) on every selected media item. Pass -1 for either to leave it unchanged.
Inputs: fade_in_sec, fade_out_sec.
set_time_selectionC
Set the time selection (loop range) in seconds.
Inputs: end_sec (required), start_sec (required).
set_track_colorA
Set track color. r/g/b each 0..255. Use r=g=b=0 to clear (revert to default).
Inputs: b (required), g (required), r (required), index (required).
set_track_folder_depthA
Set folder structure depth for a track. 1 = this track starts a folder, 0 = normal (default), -1 = end of one folder, -2 = end of two folders, etc. Use this to group tracks: e.g. set depth=1 on a 'Drums' track and depth=-1 on the last child.
Inputs: depth (required), index (required).
set_track_muteC
Mute or unmute a track.
Inputs: index (required), muted (required).
set_track_panC
Set track pan. -1.0 = full left, 0 = center, 1.0 = full right.
Inputs: pan (required), index (required).
set_track_record_armC
Arm or disarm a track for recording.
Inputs: armed (required), index (required).
set_track_soloC
Solo or unsolo a track.
Inputs: index (required), soloed (required).
set_track_volume_dbB
Set track volume in dB. Use -150 for -inf (silent). 0 = unity. Typical mix range: -60..+12.
Inputs: db (required), index (required).
split_items_at_timeA
Split every item that crosses time_sec at that time. If selected_only is true, only split currently-selected items. Returns count of items created.
Inputs: time_sec (required), selected_only.
stopB
Stop playback or recording.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 50 tools
Most tools target distinct resources or actions, with clear separation between track, item, MIDI, FX, and render operations. However, the render family (render, render_with_current_settings, batch_export_regions) and the reaper_eval catch-all slightly overlap with typed tools, and ping/bridge_status both serve diagnostic purposes.
Nearly all tools use consistent snake_case with predictable verb_noun patterns (set_track_volume_db, list_tracks, add_fx). A few bare verbs (play, stop, record, render, ping) and new_project deviate slightly, but the overall convention is coherent and readable.
50 tools is an extreme mismatch for a single MCP server; many granular setters (set_track_mute, set_track_solo, set_track_pan, etc.) could be merged into a unified update_track operation. The rubric explicitly flags 50+ tools as requiring a score of 1.
The surface covers core lifecycle operations for projects, tracks, regions, MIDI, FX, rendering, and batch processing, with reaper_eval providing an escape hatch for anything missing. Typed gaps remain for item-level CRUD (delete/copy/trim items), automation envelopes, sends, and tempo/meter, which will force agents to use eval for common tasks.
Maintenance
Related MCP Connectors
Read and edit DAW projects as an agent, save native Logic projects, convert projects between DAWs
Remote MCP server for audio stem separation, denoise, reverb, and MIDI export.
214 tools for AI agents over one MCP endpoint: image, video, audio, 3D, data, storage, mail, GPUs.
Compose, mix, master and export in Logic Pro, REAPER or Ableton Live by talking to an AI engineer.
Related MCP Servers
- AlicenseCqualityCmaintenanceEnables AI assistants to control REAPER DAW via the Model Context Protocol, including track, FX, MIDI, and audio operations.4790MIT
- AlicenseCqualityAmaintenanceA comprehensive MCP server that enables AI assistants to control REAPER DAW for mixing, mastering, MIDI composition, and full music production workflows with 130 tools.1872,642 PyPI104MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI-powered music production by integrating with REAPER DAW via MCP protocol, allowing users to control project settings, MIDI editing, and VST plugins through natural language.11-
- FlicenseNot gradedqualityBmaintenanceEnables MCP-capable agents to control REAPER through safe, typed operations for game audio workflows such as creating variations and rendering WAV files.1-