# TwelveTake-Studios/reaper-mcp [Health: Active]

**Category:** 🎨 Art & Culture  
**Repository:** https://github.com/TwelveTake-Studios/reaper-mcp  
**GitHub Stars:** 95  
**Views:** 6  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/twelvetake-studios-reaper-mcp

## Description
MCP server enabling AI assistants to control REAPER DAW for mixing, mastering, MIDI composition, and full music production with 129 tools

## Tools
Capabilities this server exposes over MCP:

- **get_track_count** — Get the total number of tracks in the current REAPER project (excluding master track).
- **get_track** — Get information about a track.

Returns:
    Object with 'info': guid, name, volume, volume_db, pan, muted, soloed,
    has_midi, has_audio, fx_names, role.
- **get_all_tracks** — Get information about all tracks in the project.
- **get_master_track** — Get information about the master track.
- **insert_track** — Insert a new track at the specified index.

Args:
    index: Position to insert track (0-based). If not specified, adds at end.
    name: Optional name for the new track.

Returns:
    Info about the created track.
- **delete_track** — Delete a track.

Args:
    track_index: Track index to delete (0-based). Cannot delete master track (-1).
- **set_track_name** — Set the name of a track.

Args:
    name: New name for the track.
- **set_track_volume** — Set the volume of a track in decibels.

Args:
    volume_db: Volume in dB (0 = unity gain, -inf to +12 typical range).
- **set_track_pan** — Set the pan position of a track.

Args:
    pan: Pan position from -1.0 (full left) to 1.0 (full right). 0 = center.
- **set_track_mute** — Set the mute state of a track.

Args:
    mute: True to mute, False to unmute.
- **set_track_solo** — Set the solo state of a track.

Args:
    solo: True to solo, False to unsolo.
- **track_fx_get_count** — Get the number of FX plugins on a track.

Returns:
    Object with 'ret' field containing count.
- **track_fx_get_list** — Get list of all FX plugins on a track.

Returns:
    Object with 'fx' array, one entry per FX with index, name, enabled and offline,
    plus fx_count. 'enabled' is False when the FX is bypassed. Normal FX chain only,
    not input/record FX or master monitoring FX.
- **track_fx_add_by_name** — Add an FX plugin to a track by name.

Args:
    fx_name: Name of the FX plugin to add (e.g., "ReaEQ", "ReaComp", "ReaLimit").
             Use the exact plugin name as it appears in REAPER's FX browser.
    position: Optional insertion position (0-based) in the FX chain.
              Default -1 adds at the end; 0 inserts at the beginning.

Returns:
    Info about the added FX including its index.
- **track_fx_move** — Move an FX plugin to a new position within the same track's FX chain.

Args:
    fx_index: Current FX index (0-based) in the FX chain.
    new_position: Target position (0-based). 0 = beginning of the chain.
- **track_fx_delete** — Remove an FX plugin from a track.
- **track_fx_get_name** — Get the name of an FX plugin.
- **track_fx_get_enabled** — Get the enabled state of an FX plugin.

Returns:
    Object with 'ret' field (boolean).
- **track_fx_set_enabled** — Enable or disable an FX plugin.

Args:
    enabled: True to enable, False to bypass.
- **track_fx_get_num_params** — Get the number of parameters for an FX plugin.
- **track_fx_get_param_name** — Get the name of an FX parameter.
- **track_fx_get_param** — Get a specific parameter value of an FX plugin.

Returns:
    Object with value, min, max for the parameter.
- **track_fx_set_param** — Set a parameter value on an FX plugin.

Args:
    value: New value for the parameter (typically normalized 0-1, check min/max).
- **take_fx_get_count** — Get the number of FX plugins on a take.

Returns:
    Object with 'ret' field containing the FX count.
- **take_fx_get_list** — Get a list of all FX plugins on a take.

Returns:
    Object with 'fx' array, each entry having index, name, and enabled state.
- **take_fx_add_by_name** — Add an FX plugin to a take by name.

Args:
    fx_name: Name of the FX plugin to add (e.g., "ReaEQ", "ReaComp"). Use the exact
             plugin name as it appears in REAPER's FX browser.

Returns:
    Object with 'ret' field containing the new FX index (or -1 if it could not be added).
- **take_fx_delete** — Remove an FX plugin from a take.

Args:
- **take_fx_get_name** — Get the name of an FX plugin on a take.

Args:
- **take_fx_get_enabled** — Get the enabled (not bypassed) state of an FX plugin on a take.

Args:

Returns:
    Object with 'ret' field (boolean).
- **take_fx_set_enabled** — Enable or bypass an FX plugin on a take.

Args:
    enabled: True to enable, False to bypass.
- **take_fx_get_num_params** — Get the number of parameters for an FX plugin on a take.

Args:
- **take_fx_get_param_name** — Get the name of a parameter on a take's FX plugin.

Args:
- **take_fx_get_param** — Get a parameter value on a take's FX plugin.

Args:

Returns:
    Object with 'value', 'min', and 'max' for the parameter.
- **take_fx_set_param** — Set a parameter value on a take's FX plugin.

Args:
    value: New value (typically normalized 0-1; check min/max via take_fx_get_param).
- **get_takes** — List all takes of a media item.

Returns:
    Object with 'takes' array (each entry: index, name, is_active) and 'ret' = take count.
- **get_active_take** — Get the index of the active take of a media item.

Returns:
    Object with 'ret' = active take index (-1 if the item has no active take).
- **set_active_take** — Set the active take of a media item (which take plays).

Args:
- **explode_takes** — Explode all takes of a media item in place (each take becomes its own overlapping item).
- **crop_to_active_take** — Crop a media item to its active take, discarding all other takes.
- **delete_take** — Delete a specific take from a media item.

Args:
    take_index: Take index to delete (0-based). The take is activated first, then removed.
- **select_comp_lane** — Make a fixed lane play exclusively on a track (REAPER 7 lane-based comping).

The track must be in fixed-lane mode (right-click track -> Track lanes). Returns a clear
error if it is not, or if the lane index is out of range.

Args:
    lane_index: Fixed lane index to play exclusively (0-based).
- **create_send** — Create a send from one track to another.

Args:
    src_track: Source track index (0-based).
    dest_track: Destination track index (0-based).

Returns:
    Object with send_index.
- **delete_send** — Delete a send from a track.

Args:
    track_index: Source track index (0-based).
    send_index: Send index (0-based) to delete.
- **set_send_volume** — Set the volume of a track send.

Args:
    track_index: Source track index (0-based).
    volume_db: Send volume in dB.
- **get_track_num_sends** — Get the number of sends from a track.
- **set_send_dest_channels** — Set the destination channels for a send (used for sidechain routing).

Args:
    track_index: Source track index (0-based).
    dest_chan: Destination channel pair (0=1-2 main, 2=3-4 sidechain, 4=5-6, etc.).
               For sidechain compression, use 2 to route to channels 3-4.
- **set_send_source_channels** — Set the source channels for a send.

Args:
    track_index: Source track index (0-based).
    src_chan: Source channel (-1=none, 0=stereo 1-2, 1024+n=mono from channel n).
- **setup_sidechain_send** — Create a sidechain send from one track to another track's FX sidechain input.

This creates a send routed to channels 3-4 of the destination track,
which is the standard sidechain input for compressors like ReaComp.

Args:
    src_track: Source/trigger track index (e.g., kick drum).
    dest_track: Destination track index (e.g., bass with compressor).
    volume_db: Send volume in dB (default 0dB = unity).

Returns:
    Object with send_index and routing info.
- **configure_reacomp_sidechain** — Configure ReaComp to use sidechain input for detection.

Args:
    track_index: Track index (0-based) where ReaComp is located.
    fx_index: FX index (0-based) of ReaComp in the FX chain.
    use_sidechain: True to use auxiliary input (channels 3-4), False for main input.

Returns:
    Object with configuration status.
- **setup_sidechain_compression** — Complete sidechain compression setup: creates send and configures compressor.

This is the all-in-one function for setting up sidechain compression.
It creates a send from the trigger track to the target track's sidechain input
and configures ReaComp to listen to that sidechain.

Args:
    trigger_track: Track that triggers compression (e.g., kick drum = track 0).
    target_track: Track to be compressed (e.g., bass = track 1).
    compressor_fx_index: Index of ReaComp in target track's FX chain.
    send_volume_db: Sidechain send volume in dB (default 0dB).

Returns:
    Object with complete setup info.

Example:
    For kick-triggered bass compression where:
    - Drums are on track 0
    - Bass is on track 1 with ReaComp at FX index 2
    Call: setup_sidechain_compression(0, 1, 2)
- **play** — Start playback in REAPER.
- **stop** — Stop playback in REAPER.
- **get_play_state** — Get the current playback state.

Returns:
    Object with play state info.
- **get_cursor_position** — Get the edit cursor position.

Returns:
    Object with cursor position in seconds.
- **set_cursor_position** — Set the edit cursor position.

Args:
    position: Position in seconds from project start.
- **save_project** — Save the current REAPER project.
- **get_project_path** — Get the project path.
- **get_project_name** — Get the project name.
- **get_tempo** — Get the tempo at project start as `ret`, and every tempo marker as `tempo_markers`.
- **get_time_signature** — Get the project time signature.
- **add_mastering_chain** — Add a standard mastering chain to the master track.

Adds the following plugins in order:
1. ReaEQ (corrective EQ)
2. ReaComp (glue compression)
3. ReaEQ (tonal shaping)
4. ReaLimit (brickwall limiter)

Returns:
    Object with list of added FX indices.
- **add_parallel_compression** — Set up New York style parallel compression for a track.

Creates a new bus track with heavy compression, fed by a send from the source track.

Args:
    track_index: Source track index (0-based).
    blend_db: Send level in dB for the compressed signal (default -6dB).

Returns:
    Object with bus_track_index, send_index, and compressor_fx_index.
- **create_bus** — Create a submix/stem bus and route specified tracks to it.

Args:
    name: Name for the bus track.
    source_track_indices: List of track indices to route to this bus.

Returns:
    Object with bus_track_index and routing info.
- **add_eq** — Add ReaEQ to a track.

Returns:
    Object with fx_index.
- **add_compressor** — Add ReaComp to a track.

Returns:
    Object with fx_index.
- **add_limiter** — Add ReaLimit (brickwall limiter) to a track.

Returns:
    Object with fx_index.
- **create_midi_item** — Create an empty MIDI item on a track.

Args:
    position: Start position in seconds.
    length: Length in seconds.

Returns:
    Object with item info including the new item_index.
- **get_midi_item** — Get information about a MIDI item.

Returns:
    Object with item info including position, length, note count.
- **add_midi_note** — Add a MIDI note to an item using musical timing (beats).

Args:
    pitch: MIDI note number (0-127, 60 = middle C).
    velocity: Note velocity (1-127).
    start_beat: Start position in beats from the item start (0 = first beat).
    length_beats: Note length in beats (0.25 = sixteenth, 0.5 = eighth, 1.0 = quarter).

Example:
    Four-on-the-floor kick: add_midi_note(0, 0, 36, 110, start_beat=0, length_beats=0.25)
    then start_beat=1, 2, 3.
- **add_midi_notes_batch** — Add multiple MIDI notes to an item in one call, using musical timing (beats).

Args:
    notes: List of note dicts with keys: pitch, velocity, start_beat, length_beats,
           channel (optional).

Returns:
    Object with count of notes added.
- **get_midi_notes** — Get all MIDI notes from an item.

Returns:
    Object with list of notes.
- **delete_midi_note** — Delete a MIDI note from an item.
- **clear_midi_item** — Delete all MIDI notes from an item.

Returns:
    Object with count of notes deleted.
- **set_midi_note_velocity** — Set the velocity of a MIDI note.

Args:
    velocity: New velocity (1-127).
- **transpose_midi_notes** — Transpose MIDI notes by a number of semitones (12 = an octave).

A note that would land outside pitch 0-127 keeps its original pitch and is counted in
`skipped` instead.

Args:
    semitones: Signed shift; positive is up, negative is down. 0 = no-op.

Returns:
    {ok, notes_changed, clamped, skipped, out_of_bounds, notes:[...]}, where `notes` is
    the full note list after the transform, re-indexed.
- **nudge_midi_notes** — Shift MIDI notes in time by a number of beats (+ = later, - = earlier).

Start and end move together, so note lengths are preserved. A note pushed before the
item start clamps to it and one pushed past the item end is left there; both count in
`out_of_bounds`, not `clamped`.

Args:
    amount_beats: Signed beat shift (0.25 = a 16th later, -1.0 = a beat earlier). 0 = no-op.
- **get_selected_midi_notes** — Read the MIDI notes currently SELECTED in REAPER's editor for the active take.

The escape hatch for "operate on what I've selected": select notes by hand in REAPER,
call this to see which they are, then translate that into an explicit value filter
(pitch range / beat window / channel) for the transform tools. Read-only, no undo.

Returns:
    {ok, notes:[...], ret} - the selected notes, same shape as get_midi_notes (each note
    carries item-relative start_beat/end_beat). `index` is REAPER's absolute PPQ-sorted
    note index, so a partial selection is non-contiguous. Empty selection -> notes:[].
- **select_midi_notes** — Select the MIDI notes matching the filter, as if clicked in REAPER's MIDI editor.

Args:
    selected: False deselects the matching notes instead; with no filter, clears the selection.
    exclusive: When selecting, deselect every note that does not match.

`notes_changed` counts notes whose selection flipped.
- **set_midi_note** — Edit one existing MIDI note in place: pitch, start, length and/or channel. Only the
fields you pass change, and at least one is required. (Velocity: set_midi_note_velocity.)

note_index is REAPER's PPQ-sorted index from get_midi_notes / get_selected_midi_notes and
is unstable - re-read after the edit, since the returned list reflects the new order.

Args:
    pitch: New pitch (0-127).
    start_beat: New start in beats from item start; length is preserved. A start before
        the item start clamps there and is counted in out_of_bounds, not clamped.
    length_beats: New length in beats (> 0), resized from the current start.
    channel: New MIDI channel (0-15).

Returns:
    {ok, notes_changed, clamped, skipped, out_of_bounds, notes:[...]}, or {ok:false, error}
    for a bad index, an empty edit, or an out-of-range value (nothing is written).
- **ramp_midi_note_velocities** — Apply a linear velocity ramp (crescendo / decrescendo) across MIDI notes.

Velocities interpolate by onset: the earliest note in the filtered set gets
start_velocity, the latest gets end_velocity, everything between is linear. Notes
sharing an onset (a chord) get the same velocity. Results clamp to 1-127.

Args:
    start_velocity: Velocity at the earliest onset (1-127; out of range clamps, not an error).
    end_velocity: Velocity at the latest onset (1-127).
- **scale_midi_note_velocities** — Scale MIDI note velocities: multiply, set to a fixed value, or compress toward a pivot.
Results clamp to 1-127.

Args:
    mode: "multiply" (velocity * ratio), "set" (velocity becomes `value`), or "compress"
        (pivot + (velocity - pivot) * ratio).
    ratio: Multiply factor (>= 0, no upper cap), or compress amount (0.0-1.0, where 0
        collapses every note onto the pivot and 1.0 changes nothing).
    value: Target velocity for "set" mode (1-127).
    pivot: What compress pulls toward (1-127), or -1 for the rounded mean of the matched
        notes' velocities (reported as pivot_used).

Returns:
    {ok, notes_changed, clamped, skipped, out_of_bounds, pivot_used, notes:[...]}.
- **strum_midi_notes** — Strum chords: stagger the onsets of simultaneous notes so each chord rolls out.

Only onsets move; note lengths are preserved.

Args:
    spread_beats: Total first-to-last onset span within each chord (>= 0; 0 = no-op).
    direction: "up" strikes the lowest note of a chord first, "down" the highest.
    chord_window_beats: Onset tolerance for grouping notes into one chord (0 = exact
        same onset).
- **snap_midi_notes_to_scale** — Snap off-key MIDI notes onto a scale (fix a wrong note, force a part into a key).

Notes already in the scale are left alone; each off-scale note moves to the nearest
in-scale pitch, and under `nearest` a tie resolves toward the middle of the selection.
A note with no in-scale pitch left inside 0-127 stays put and is counted in `skipped`.

Args:
    root: Root pitch class, 0-11 (0=C, 1=C#, 2=D ... 11=B).
    mode: Scale name: major, minor, harmonic_minor, melodic_minor, dorian, phrygian,
        lydian, mixolydian, locrian, major_pentatonic, minor_pentatonic, blues,
        whole_tone, chromatic (aliases: ionian, aeolian, natural_minor). Or a custom
        list of semitone intervals from the root, each 0-11 (e.g. [0,2,4,7,9]).
    direction: "nearest" (closest scale tone), "up" or "down" (that way only, skipping
        a note rather than falling back to the other direction).

Returns:
    {ok, notes_changed, clamped, skipped, out_of_bounds, notes:[...]}; `notes` is the
    post-transform list, with indices re-synced after the sort.
- **quantize_midi_notes** — Quantize MIDI note onsets onto the grid (tighten sloppy timing, add swing).

Onsets snap to the PROJECT bar/beat grid, not to an offset from the item's own start,
and note lengths are preserved: start and end move together. Notes that land past the
item end are kept, and one that would land before the item start is placed at it; both
are counted in `out_of_bounds` (`clamped` stays 0 here).

Args:
    grid: Grid spacing in beats: 0.25 = 1/16, 0.5 = 1/8, 1.0 = 1/4. Must be > 0.
    strength: 0.0-1.0. 1.0 snaps exactly onto the grid, 0.5 moves each note halfway
        there, 0.0 is a no-op.
    swing: 0.0-1.0. 0.0 = straight, 1.0 = full triplet feel (off-beats at 66.7%),
        scaling linearly between. Only the off-beat (odd) grid cells are delayed.
- **stretch_midi_notes** — Stretch or compress MIDI timing (half-time, double-time, or any ratio).

Each targeted note scales as a rigid unit about one fixed pivot: its distance from the
pivot and its own length both multiply by `factor`, so the rhythm is preserved and only
the speed changes. Notes that land past the item end are kept as-is; one pushed before
the item start begins at the item start but keeps its scaled end, so it comes out
shorter. Both are counted in `out_of_bounds` (`clamped` stays 0 here).

Args:
    factor: Time scale ratio, must be > 0. 2.0 = twice as long (half-time), 0.5 = half
        as long (double-time).
    pivot_beat: The fixed point, in beats from the item start; may be negative. None =
        the earliest targeted onset.
- **legato_midi_notes** — Close the gaps in a MIDI line (legato), or set every note to one length.

Only note ends move; starts are never touched. "connect" extends each note's end to the
next onset and never shortens anything; a gap wider than max_gap_beats is left as a rest
and counted in gaps_preserved, and the last note is left alone. "fixed" instead sets every
targeted note's length to length_beats. Notes whose new end passes the item end are kept
and reported in out_of_bounds.

Args:
    mode: "connect" (extend each end to the next onset) or "fixed" (set every length).
    voice: connect only. "chordal" extends to the next onset of any note, so a chord's
        notes move together; "per_pitch" extends to the next note of the SAME pitch and
        channel, keeping interleaved voices independent.
    max_gap_beats: connect only. Gaps wider than this are left as rests (>= 0).
    length_beats: fixed only. The length every targeted note is set to (> 0).

Returns:
    {ok, notes_changed, clamped, skipped, out_of_bounds, gaps_preserved, notes:[...]}.
- **humanize_midi_notes** — Humanize MIDI: nudge timing and velocity by small random amounts, reproducibly.

Each note gets its own timing and velocity offset drawn from a bell curve. Note lengths
are preserved (start and end move together) and pitches are never touched. The randomness
is seeded, so the same take with the same seed and settings gives identical results every
time. Velocities are clamped to 1-127 and counted in clamped; notes pushed past the item
end are kept and reported in out_of_bounds.

Unlike the other timing tools, a note pushed before the item start is placed at the
item start and counted in out_of_bounds, not clamped; clamped here counts only the
velocity clamp.

Args:
    timing: Timing spread in beats (standard deviation); 0.02 is a subtle human feel,
        0.0 leaves timing alone.
    velocity: Velocity spread (standard deviation, in velocity units); 0.0 leaves
        velocity alone.
    seed: Any integer. The same seed, settings and take give the same result.
    max_sigma: Cap on how far one note may stray, in multiples of the spread.
- **remove_overlapping_midi_notes** — Clean up overlapping MIDI notes (same pitch stacked on itself).

Two notes conflict only if they share a pitch AND a channel AND overlap in time, so a
chord is never a conflict and notes that merely touch are left alone. "trim" shortens the
earlier note to stop where the next begins, losing nothing; "delete" drops one note of
each overlapping pair, keeping the louder (ties go to the longer note).

Either mode can remove notes: notes stacked on the exact same onset collapse to the
loudest, since there is nothing to trim between them, and a trim left shorter than
min_length_beats is removed rather than left as a click.

Args:
    mode: "trim" (shorten the earlier note) or "delete" (drop the quieter note).
    min_length_beats: A trimmed note left shorter than this is removed instead. Default
        1/128 of a beat; 0 disables it.
    pitch_low, pitch_high: Notes outside the filter are invisible: never touched,
        and never counted as an overlap partner.

Returns:
    {ok, mode, notes_changed, clamped, skipped, out_of_bounds, notes_removed, trimmed,
    deduped, deleted, notes:[...]} where notes_removed = deduped + deleted.
- **insert_audio_file** — Insert an audio file onto a track.

Args:
    file_path: Full path to the audio file.
    position: Position in seconds.

Returns:
    Object with track_index, item_index of the created item, and position.
- **get_track_items** — Get all media items on a track.

Returns:
    Object with list of items.
- **get_item_info** — Get information about a media item.

Returns:
    Object with item properties (position, length, take info, etc.).
- **set_item_position** — Set the position of a media item.

Args:
    position: New position in seconds.
- **set_item_length** — Set the length of a media item.

Args:
    length: New length in seconds.
- **delete_item** — Delete a media item.
- **duplicate_item** — Duplicate a media item.

Returns:
    Object with new item info.
- **split_item** — Split a media item at a position.

Args:
    position: Split position in seconds (absolute project time).

Returns:
    Object with info about both resulting items.
- **set_item_mute** — Mute or unmute a media item.

Args:
    mute: True to mute, False to unmute.
- **set_item_volume** — Set the volume of a media item.

Args:
    volume_db: Volume in dB.
- **set_item_fade_in** — Set the fade-in length of a media item.

Args:
    length: Fade-in length in seconds.
- **set_item_fade_out** — Set the fade-out length of a media item.

Args:
    length: Fade-out length in seconds.
- **set_tempo** — Set the project tempo.

Args:
    bpm: Tempo in beats per minute.
- **set_time_signature** — Set the project time signature.

Args:
    numerator: Beats per measure (e.g., 4 for 4/4).
    denominator: Beat unit (e.g., 4 for quarter note).
- **create_project** — Create a new REAPER project.

Note: REAPER has no API to name a project that has never been saved, so this server
has no way to name one either. The removed `name` parameter never took effect.
- **open_project** — Open a REAPER project file.

Args:
    path: Full path to the .rpp file.
- **render_project** — Render the project's master mix to an audio file (uses REAPER's last render settings
for format details; a .wav extension selects WAV output).

If the target file already exists, this returns an error unless overwrite=True
(which deletes the existing file first). This is explicit because REAPER's own
behavior on existing files (prompt vs auto-increment) is a user preference, and the
overwrite prompt blocks unattended rendering.

Args:
    output_path: Full path for output file (extension determines format).
    start_time: Start time in seconds (None = project start).
    end_time: End time in seconds (None = project end).
    tail_seconds: Extra seconds to render at end for reverb tails.
    overwrite: True to replace an existing file at output_path.

Returns:
    Object with render status and REAPER's computed output target(s).
- **measure_loudness** — Measure loudness as REAPER's loudness window does: integrated LUFS, short-term and
momentary max, loudness range, sample peak, plus true peak.

Target: the master (default), a track, or one item (its track's output over the item,
other items muted). start_time/end_time limit it to a range. It runs a render dry run, so
it writes no files, puts selections back and adds no undo step. Measuring the master marks
the project as modified, even though nothing in it changes.

Returns:
    integrated_lufs, short_term_max_lufs, momentary_max_lufs, loudness_range_lu,
    sample_peak_dbfs, true_peak_dbtp, samples_over_0dbfs, duration; a note when a
    figure is approximate or unavailable.
- **measure_spectrum** — Measure tonal balance and stereo image: octave-band levels (31.5 Hz to 16 kHz),
spectral centroid, tilt in dB per octave, stereo correlation overall and below 150 Hz,
side-to-mid level and left/right balance.

Same targets and range as measure_loudness. Levels are dBFS with a full-scale sine at 0,
as in REAPER. Needs the TwelveTake MCP Analyzer, which --install-bridge installs.
- **render_region** — NOT IMPLEMENTED. Use render_project with the region's start/end from get_regions.

Args:
    output_path: Full path for output file.
- **add_marker** — Add a marker at a position.

Args:
    position: Position in seconds.
    name: Marker name.
    color: Marker color (0 = default).

Returns:
    Object with marker index.
- **add_region** — Add a region.

Args:
    start: Start position in seconds.
    end: End position in seconds.
    name: Region name.
    color: Region color (0 = default).

Returns:
    Object with region index.
- **get_markers** — Get all markers in the project.

Returns:
    Object with list of markers (position, name, index).
- **get_regions** — Get all regions in the project.

Returns:
    Object with list of regions (start, end, name, index).
- **delete_marker** — Delete a marker by index.
- **delete_region** — Delete a region by index.
- **go_to_marker** — Move the edit cursor to a marker.
- **go_to_region** — Move the edit cursor to a region start.
- **get_track_envelope** — Get a track envelope by name.

Args:
    envelope_name: Envelope name (e.g., "Volume", "Pan", "Mute").

Returns:
    Object with envelope info.
- **get_envelope_point_count** — Get the number of points in an envelope.

Args:
    envelope_name: Envelope name.

Returns:
    Object with point count.
- **add_envelope_point** — Add a point to an envelope.

Args:
    envelope_name: Envelope name.
    time: Time position in seconds.
    value: Envelope value (0.0-1.0 for most envelopes).
    shape: Point shape (0=linear, 1=square, 2=slow start/end, 3=fast start, 4=fast end, 5=bezier).

Returns:
    Object with point index.
- **get_envelope_points** — Get all points from an envelope.

Args:
    envelope_name: Envelope name.

Returns:
    Object with list of points (time, value, shape).
- **delete_envelope_point** — Delete an envelope point.

Args:
    envelope_name: Envelope name.
- **clear_envelope** — Delete all points from an envelope.

Args:
    envelope_name: Envelope name.
- **set_track_automation_mode** — Set the automation mode for a track.

Args:
    mode: 0=trim/read, 1=read, 2=touch, 3=write, 4=latch.
- **arm_track_envelope** — Arm or disarm an envelope for recording.

Args:
    envelope_name: Envelope name.
    arm: True to arm, False to disarm.
- **get_fx_envelope** — Get or create an automation envelope for an FX parameter.

This enables automation of any FX parameter (e.g., a flanger knob in Guitar Rig).
The envelope is created if it doesn't exist.

Args:
    param_index: Parameter index (0-based). Use track_fx_get_num_params() to find available parameters.

Returns:
    Object with envelope_name, param_name, point_count, and indices.
- **add_fx_envelope_point** — Add an automation point to an FX parameter envelope.

Args:
    time: Time position in seconds.
    value: Parameter value (typically 0.0-1.0, normalized).
    shape: Point shape (0=linear, 1=square, 2=slow start/end, 3=fast start, 4=fast end, 5=bezier).

Returns:
    Object with point_index and confirmation.
- **get_fx_envelope_points** — Get all automation points from an FX parameter envelope.

Returns:
    Object with list of points (time, value, shape, tension, selected).
- **delete_fx_envelope_point** — Delete an automation point from an FX parameter envelope.

Args:
    point_index: Point index (0-based) to delete.
- **clear_fx_envelope** — Clear all automation points from an FX parameter envelope.

Returns:
    Object with deleted_count.
- **undo** — Undo the last action in REAPER.

Returns:
    Object with undo description.
- **redo** — Redo the last undone action in REAPER.

Returns:
    Object with redo description.
- **get_undo_state** — Get the current undo/redo state.

Returns:
    Object with undo and redo descriptions.
- **select_track** — Select a track.

Args:
    exclusive: If True, deselect other tracks first.
- **select_all_tracks** — Select all tracks.
- **unselect_all_tracks** — Unselect all tracks.
- **get_selected_tracks** — Get indices of all selected tracks.

Returns:
    Object with list of selected track indices.
- **select_all_items** — Select all media items.
- **unselect_all_items** — Unselect all media items.
- **get_selected_items** — Get all selected media items.

Returns:
    Object with list of selected items.
- **copy_selected_items** — Copy selected items to clipboard.
- **cut_selected_items** — Cut selected items to clipboard.
- **paste_items** — Paste items from clipboard at edit cursor.
- **delete_selected_items** — Delete all selected items.
- **set_time_selection** — Set the time selection.

Args:
    start: Start time in seconds.
    end: End time in seconds.
- **get_time_selection** — Get the current time selection.

Returns:
    Object with start and end times.
- **clear_time_selection** — Clear the time selection.
- **set_track_phase** — Set the phase inversion of a track.

Args:
    invert: True to invert phase, False for normal.
- **set_track_width** — Set the stereo width of a track.

Args:
    width: Width value (0=mono, 1=stereo, 2=200% width).
- **set_track_as_folder** — Set a track as a folder parent or child.

Args:
    folder_depth: 0=normal, 1=folder parent, -1=end of folder.
- **arm_track** — Arm or disarm a track for recording.

Args:
    arm: True to arm, False to disarm.
- **set_track_input** — Set the record input for a track.

Args:
    input_index: Input index (-1=no input, 0+=hardware inputs, 4096+=virtual MIDI).
- **set_track_monitor** — Set the monitor mode for a track.

Args:
    monitor: 0=off, 1=normal, 2=not when playing.
- **set_track_color** — Set the color of a track.

Args:
    r: Red component (0-255).
    g: Green component (0-255).
    b: Blue component (0-255).
- **get_track_peak** — Get the current peak level of a track.

Args:
    channel: Channel (0=left, 1=right).

Returns:
    Object with peak value in dB.
- **get_track_peak_hold** — Get the peak hold level of a track (highest peak since meters were last reset).

Returns the max peak from a previous playback without needing to be actively
playing - play the project, stop, then call this for gain staging.

Args:
    channel: Channel (0=left, 1=right).

Returns:
    Object with peak hold value in dB.
- **clear_all_peak_indicators** — Clear the peak hold indicators on all tracks (including master).

Resets the held peak values that accumulate during playback. Use before a
fresh playback pass when you want clean readings for gain staging.
- **get_track_master_send** — Get the master/parent send state of a track.

Returns:
    Object with 'ret' field (1 = enabled, 0 = disabled).
- **set_track_master_send** — Enable or disable the master/parent send on a track.

When enabled, the track's audio routes to its parent folder track (or the
master if it has no parent). Disable it when a track should only output
through its sends (e.g., routed exclusively to a bus).

Args:
    enabled: True to enable, False to disable.
- **run_action** — Run a REAPER action by command ID.

Args:
    action_id: REAPER action/command ID number.
- **run_action_by_name** — Run a REAPER action by its named command id.

Named commands (e.g. ReaScripts "_RS12345" or SWS "_SWS_...") are resolved
to a numeric command id via NamedCommandLookup before firing. A purely numeric
string (e.g. "40297") is treated as a built-in command id and run directly;
prefer run_action(action_id) for built-ins.

Args:
    action_name: Named command id (e.g. "_RS12345") or a numeric command id string.

Returns:
    If the named command cannot be resolved,
    returns {"ok": False, "error": ...} without firing any action.
- **get_fx_presets** — Get list of presets available for an FX.

Returns:
    Object with list of preset names.
- **get_fx_preset** — Get the current preset name of an FX.

Returns:
    Object with current preset name.
- **set_fx_preset** — Set the preset of an FX.

Args:
    preset_name: Preset name.
- **save_fx_preset** — Save the current FX settings as a preset.

Args:
    preset_name: Name for the new preset.
- **get_eq_bands** — Get all ReaEQ band settings in one structured call.

Args:
    fx_index: FX index (0-based) of ReaEQ in the FX chain.

Returns:
    Object with a 'bands' list. Each band has band_index, bandtype,
    bandtype_name, bandidx, paramtype, paramtype_name, normval, the
    REAPER-formatted value, and (for gain params) the computed gain_db.
- **set_eq_band** — Set a ReaEQ band parameter.

Pass real values by default: frequency in Hz (paramtype 0), gain in dB
(paramtype 1), or Q (paramtype 2). Gain is converted to ReaEQ's normalized
curve internally; freq and Q are sent raw.

Args:
    fx_index: FX index (0-based) of ReaEQ.
    bandtype: -1=master gain, 0=hipass, 1=loshelf, 2=band, 3=notch,
              4=hishelf, 5=lopass, 6=bandpass, 7=parallel bandpass.
    bandidx: Band index within that type (0=first). Ignored for master gain.
    paramtype: 0=frequency (Hz), 1=gain (dB), 2=Q. Ignored for master gain.
    value: The value, in real units unless is_normalized=True.
    is_normalized: If True, value is a raw 0-1 normalized value written directly.
- **get_eq_band_enabled** — Check whether a ReaEQ band is enabled.

Args:
    fx_index: FX index (0-based) of ReaEQ.
    bandtype: Band type (0=hipass, 1=loshelf, 2=band, 3=notch, 4=hishelf, 5=lopass).
    bandidx: Band index within that type (0=first).

Returns:
    Object with 'ret' boolean (true=enabled).
- **set_eq_band_enabled** — Enable or disable a ReaEQ band.

Args:
    fx_index: FX index (0-based) of ReaEQ.
    bandtype: Band type (0=hipass, 1=loshelf, 2=band, 3=notch, 4=hishelf, 5=lopass).
    bandidx: Band index within that type (0=first).
    enabled: True to enable, False to disable.
- **find_eq** — Find ReaEQ on a track, optionally adding it if absent.

Args:
    instantiate: If True and ReaEQ is not present, add it.

Returns:
    Object with 'ret' = the FX index of ReaEQ, or -1 if not found.
- **get_track_fx_chunk** — Get the raw state chunk from an FX plugin (includes preset/state data).

Useful for reading VSTi state data like Toontrack EZkeys chord progressions.
The chunk contains the full serialized state of the plugin.

Returns:
    Object with 'chunk' containing the FX state data string.
- **get_project_length** — Get the length of the project (end of last item).

Returns:
    Object with project length in seconds.
- **get_project_summary** — Get a comprehensive summary of the current REAPER project.

Returns everything needed to understand the project state and give
useful mixing/production advice in a single call.

Returns:
    Object with:
    - project_name: Name of the project file
    - project_path: Full path to the project
    - tempo: Project tempo in BPM
    - time_signature: {numerator, denominator}
    - project_length: Length in seconds
    - track_count: Total number of tracks
    - tracks: List of track info objects, each containing:
        - index: Track index (0-based)
        - name: Track name
        - volume_db: Volume in decibels
        - pan: Pan position (-1 to 1)
        - mute: Boolean mute state
        - solo: Boolean solo state
        - fx_count: Number of FX plugins
        - fx_names: List of FX plugin names
    - master: Master track info {volume_db, fx_count, fx_names}
    - markers: List of {index, position, name}
    - regions: List of {index, start, end, name}
- **get_play_position** — Get the current playback position.

Returns:
    Object with play position in seconds.
- **record** — Start recording in REAPER.
- **pause** — Pause playback in REAPER.
- **toggle_repeat** — Toggle repeat/loop mode.

Returns:
    Object with new repeat state.
- **get_repeat_state** — Get the current repeat state.

Returns:
    Object with repeat state (true/false).
- **zoom_to_selection** — Zoom the arrange view to the time selection.
- **zoom_to_project** — Zoom the arrange view to show the entire project.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "reaper-mcp": {
    "command": "uvx",
    "args": ["twelvetake-reaper-mcp"]
  }
}
```

## Documentation

## What TwelveTake-Studios/reaper-mcp does

TwelveTake-Studios/reaper-mcp lets an MCP-compatible AI assistant operate REAPER projects. Its coverage spans track inspection and editing, FX management, routing, automation, MIDI composition and editing, audio-item operations, markers and regions, and audio measurement.

Track tools can report project and master-track details, create or remove tracks, rename tracks, adjust volume and pan, and change mute or solo state. FX tools work with both track and take chains: an assistant can list plugins, add them by the exact name shown in REAPER, move or remove them, bypass or enable them, and read or change plugin parameters.

Higher-level workflow operations combine several REAPER actions. Examples include creating a bus, setting up sidechain compression, adding a mastering chain, configuring parallel compression, and retrieving a project summary containing tracks, FX, markers, regions, tempo, and time signature.

## How it works

The Python MCP process communicates with a Lua bridge running inside REAPER. The bridge is loaded as a ReaScript and remains active in the background while REAPER is open. The MCP server is normally launched over standard input and output by an MCP client, commonly through `uvx`.

The measurement features also use a TwelveTake analyzer JSFX installed in REAPER. Measurement coverage includes loudness, loudness range, true peak, octave-band spectrum, and stereo correlation for the master, a track, or an item. Changes made through the server are recorded as named, individual steps in REAPER's undo history, allowing a tool call to be reversed with REAPER's normal undo command.

## Setup and configuration

REAPER, Python 3.10 or newer, and an MCP-compatible AI assistant are required. The project supports recent REAPER versions, with the documented live test suite covering REAPER 7.79.

Install the bridge and analyzer with the package command:

```bash
uvx twelvetake-reaper-mcp --install-bridge
```

The command places the Lua script in REAPER's Scripts folder and installs the analyzer under `Effects/TwelveTake`. A custom Scripts path can be supplied for portable or nonstandard REAPER installations. The bridge must then be loaded and run from REAPER's Actions list. ReaPack and manual installation are also supported.

To start the bridge whenever REAPER launches, use `--autostart`; `--remove-autostart` removes that startup entry. The MCP server itself can be added to a client using a standard stdio configuration:

```json
{
  "mcpServers": {
    "reaper": {
      "command": "uvx",
      "args": ["twelvetake-reaper-mcp"]
    }
  }
}
```

VS Code uses a top-level `servers` configuration with an explicit `stdio` type. The server can also be run with `pipx run twelvetake-reaper-mcp`.

## Tools and capabilities

- Inspect project, master-track, track, take, FX, parameter, marker, region, tempo, and time-signature state.
- Create, rename, modify, route, and remove tracks, including buses and parallel-compression setups.
- Add, reorder, bypass, delete, and parameterize track or take FX.
- Create and edit MIDI items and notes, including quantization, transposition, humanization, scale snapping, stretching, legato, strumming, and velocity changes.
- Import, split, duplicate, position, mute, and fade audio items.
- Create automation envelopes and points, set automation modes, manage markers and regions, and render by region.
- Measure loudness, true peak, loudness range, spectrum, and stereo correlation.

## Limitations and notes

FX must be referenced using the exact plugin name shown in REAPER's FX browser. Track indexes are zero-based, and the master track cannot be deleted. Normal track FX-chain tools do not cover input or record FX, or master monitoring FX. The analyzer installation is needed for measurement tools but not for the other capabilities.

_Full upstream README: https://allmcps.com/mcp/twelvetake-studios-reaper-mcp/readme_

