Skip to main content
Glama
reaper-mcp-bridge

reaper-mcp-bridge

by Echo722

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
        ▼
REAPER

Design 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_eval as 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-bridge

This 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 --autostart

This 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_data

Verify end-to-end:

reaper-mcp-bridge doctor

3. Register the server with your agent (once per client)

Claude Code

claude mcp add --scope user reaper -- reaper-mcp-bridge

Claude 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_$num starting from 01."

  • "Export every region to D:\bounces\session1\, named after the region."

Related MCP server: reaper-mcp

Updating

uv tool upgrade reaper-mcp-bridge

Then 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.zip

To update, run the same command with --reinstall added. Everything else in Quick start stays the same.

Tool overview

Domain

Tools

Diagnostics

ping, bridge_status, reaper_eval

Project

get_project_info, list_tracks, list_regions, list_markers, new_project, save_project_as

Tracks

add_track, delete_track, rename_track, set_track_volume_db, set_track_pan, set_track_mute, set_track_solo, set_track_record_arm, set_track_color, set_track_folder_depth, select_tracks

Record / edit

play, stop, record, set_cursor, set_time_selection, clear_time_selection, split_items_at_time, move_selected_items, set_selected_item_fades, glue_selected_items, set_record_input, select_items_on_track

MIDI

insert_midi_item, insert_midi_notes, create_chord_progression, quantize_midi_item

Mixing

add_fx, remove_fx, list_fx, set_fx_param, set_fx_enabled, set_master_volume_db

Render

render_with_current_settings, render, get_render_settings

Batch

batch_rename_items, batch_rename_regions, batch_export_regions, normalize_loudness, apply_template

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 listening line in REAPER's console — re-run reaper-mcp-bridge install-bridge --autostart and restart REAPER, or load Scripts/reaper_mcp_bridge.lua manually via the Actions list.

  • REAPER is open but the bridge never starts — a startup dialog (e.g. "Choose Project" / crash recovery) blocks __startup.lua until 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 tools
add_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

    B3.2/5.0

    Scored across 50 tools

    Disambiguation4/5

    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.

    Naming Consistency4/5

    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.

    Tool Count1/5

    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.

    Completeness4/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers