Skip to main content
Glama
reaper-reapy-mcp
by wegitor

Reaper and MCP or AI integration

A Python application for controlling REAPER Digital Audio Workstation (DAW) using the MCP(Model context protocol).

REAPER MCP MIDI generation Demo

REAPER MCP project features Demo

Features

  • Track Management: Create, rename, and color tracks

  • FX Management: Add, remove, and control effect parameters

  • Project Control: Set tempo, manage regions and markers

  • Master Track Control: Volume, pan, mute, and solo operations

  • MIDI Operations: Create items, add/get notes, clear items with musical positioning

  • Audio Item Operations: Insert, duplicate, modify with enhanced positioning support

  • Dual Position Format: Support both time (seconds) and measure:beat notation

  • Reliable Duplication: Uses REAPER's built-in commands for accurate item copying

  • MCP Integration: Model Context Protocol server for AI assistant control

Related MCP server: ReaperMCP

Status

  • Checked on Linux: Yes

  • MCP HTTP Mode: Supported for parameters

Requirements

  • Python 3.7+

  • REAPER DAW

  • python-reapy Python module

  • mcp[cli] package for MCP server

  • Internet connection (for downloading sample audio file)

Installation

  1. Install REAPER if you haven't already

  2. Enable reapy server via REAPER scripting add reaper_side_enable_server.py to reaper actions and run it inside reaper studio

  3. Install the package:

    # From PyPI
    pip install reaper_reapy_mcp
    
    # From GitHub repository
    pip install git+https://github.com/wegitor/reaper-reapy-mcp.git
  4. Enable python in REAPER

The wheel package includes all necessary dependencies and can be used in other Python projects that need REAPER integration. The project uses pyproject.toml for modern Python packaging configuration, which provides better dependency management and build system configuration.

Sample Audio File

The application uses a sample MP3 file for testing audio operations. The file will be automatically downloaded when needed from:

https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.mp3

This is a short Star Wars theme clip that's commonly used for testing audio applications.

Running the Server

You can run the server using uv directly:

uv --directory <project_path> run -m reaper_reapy_mcp

For the current directory and http MCP mode:

uv --directory . run -m reaper_reapy_mcp --mode http

For example, on Windows:

uv --directory C:\path\to\reaper_reapy_mcp run -m reaper_reapy_mcp

Or using the Python module directly after installation:

python -m reaper_reapy_mcp

HTTP Mode

Run the server in HTTP mode with default settings:

python -m reaper_reapy_mcp --mode http

Run with custom host and port:

python -m reaper_reapy_mcp --mode http --http-host example_host --http-port 3958

Use the MCP inspector to test the tools:

test_mcp.bat

Available MCP tools:

Track Management

  • test_connection: Verify connection to REAPER

  • create_track: Create a new track

  • rename_track: Rename an existing track

  • set_track_color: Set track color

  • get_track_color: Get track color

  • get_track_count: Get number of tracks in project

  • get_track_list: Get list of all tracks with their properties

FX Management

  • add_fx: Add an FX to a track

  • remove_fx: Remove an FX from a track

  • set_fx_param: Set FX parameter value

  • get_fx_param: Get FX parameter value

  • get_fx_param_list: Get list of FX parameters

  • get_fx_list: Get list of FX on a track

  • get_available_fx_list: Get list of available FX plugins

  • toggle_fx: Toggle FX enable/disable state

Project Control

  • set_tempo: Set project tempo

  • get_tempo: Get current tempo

  • get_time_signature: Get current time signature

  • set_project_time_signature: Set project default time signature

  • set_time_signature: Set time signature at position

  • create_region: Create a region

  • delete_region: Delete a region

  • create_marker: Create a marker

  • delete_marker: Delete a marker

  • render_project: Render project to audio file

Master Track

  • get_master_track: Get master track information

  • set_master_volume: Set master track volume

  • set_master_pan: Set master track pan

  • toggle_master_mute: Toggle master track mute

  • toggle_master_solo: Toggle master track solo

MIDI Operations

  • create_midi_item: Create an empty MIDI item on a track

    • Supports both time (seconds) and measure:beat positioning

  • add_midi_note: Add a MIDI note to a MIDI item

  • add_midi_notes: Add multiple MIDI notes at once

  • get_midi_notes: Get all MIDI notes from a MIDI item

  • clear_midi_item: Clear all MIDI notes from a MIDI item

Audio Item Operations

  • insert_audio_item: Insert an audio file as a media item

    • Supports both time (seconds) and measure:beat positioning

  • duplicate_item: Duplicate an existing item (MIDI or audio)

    • Uses REAPER's built-in duplication for reliable copying

    • Supports both time (seconds) and measure:beat positioning

  • get_item_properties: Get properties of a media item

  • set_item_position: Set the position of a media item

    • Supports both time (seconds) and measure:beat positioning

  • set_item_length: Set the length of a media item

  • delete_item: Delete a media item

  • get_items_in_time_range: Get items within a time range

    • Supports both time (seconds) and measure:beat positioning

Item ID System

All item operations use a sequential index system (0..n) for item identification. This makes it easier to work with items in scripts and automation:

  • Item IDs are zero-based indices

  • Each track maintains its own sequence of item indices

  • Indices are stable until items are deleted or reordered

  • All item operations (MIDI, audio, properties) use the same indexing system

Position Format Support

Many MCP tools now support dual position formats for enhanced musical workflow:

Time Format (seconds)

{
  "start_time": 15.5,
  "new_time": 30.0
}

Measure:Beat Format

{
  "start_measure": "3:2,500",
  "new_measure": "5:1,000"
}

Format: "measure:beat,fraction" where:

  • measure: 1-based measure number

  • beat: 1-based beat number

  • fraction: milliseconds (000-999) representing fraction of a beat

  • Example: "4:2,500" = measure 4, beat 2, half beat (500ms)

Tools Supporting Both Formats:

  • create_midi_item - position via start_time OR start_measure

  • insert_audio_item - position via start_time OR start_measure

  • duplicate_item - position via new_time OR new_measure

  • set_item_position - position via new_time OR new_measure

  • get_items_in_time_range - range via time OR measure parameters

Claude configuration (with uv run):

{
    "mcpServers": {
        "reaper-reapy-mcp": {
            "type": "stdio",
            "command": "uv",
            "args": [
                "--directory",
                "<path to folder>",
                "run",
                "-m",
                "reaper_reapy_mcp"
            ]
        }
    }
}

Claude configuration direct:

{
    "mcpServers": {
        "reaper-reapy-mcp": {
            "type": "stdio",
            "command": "python",
            "args": [
                "-m",
                "reaper_reapy_mcp"
            ]
        }
    }
}

or

{
    "mcpServers": {
        "reaper-reapy-mcp": {
            "type": "stdio",
            "command": "python",
            "args": [
                "<path to folder>\\src\\reaper_reapy_mcp.py"
            ]
        }
    }
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Available Tools

47 tools
add_fxC

Add an FX to a track.

Inputs: fx_name (required), track_index (required). Returns: result

add_midi_noteA

Add a MIDI note to a MIDI item. Reaper format 2.1.00 should be converted to 2:1,000.

Important: Please check MIDI item length in which you want to add the note. If the note extends beyond the item bounds, create another one or resize existing before note adding. Double-check the item's starting position before adding it. Notes positioned before the item's position won't be added.

Item Identification - TWO ways to specify which item:

  1. Using track_pos_idx (integer):

    • Pass the simple index number from create_midi_item response

    • Example: item=track_pos_idx=0 for first item, item=track_pos_idx=1 for second item

    • Fast and easy but may change if items are reordered

  2. Using direct_item_id (string):

    • Pass the exact string ID from create_midi_item or get_items_in_time_range

    • Example: item=direct_item_id="MediaItem*0x000001234567890A"

    • Stable and reliable, won't change even if items move

The system automatically detects which type you're using.

Note about positioning:

  • start_time and start_measure specify ABSOLUTE position in the project timeline

  • The note will be placed at this absolute position, regardless of item location

  • Example: start_measure="5:1,000" means measure 5 in the project, not 5 measures into the item

Args: track_index: 0-based track index (0 = first track, 1 = second, etc.) Important: REAPER UI displays "Track 1" but API uses index 0. item: EITHER an integer track_pos_idx (0, 1, 2...) OR a string direct_item_id pitch: MIDI note pitch (0-127) start_time: ABSOLUTE start position in seconds in the project timeline (optional if start_measure is provided) start_measure: ABSOLUTE start position as "measure:beat,fraction" in the project timeline (optional if start_time is provided) length_time: Duration in seconds from note start (from start_time or start_measure)(optional if length_measure is provided) length_measure: Duration as "measure:beat,fraction" from note start (e.g., "0:2,000" = 2 beats from start_time or start_measure)(optional if length_time is provided). Also remember 2:0,0 is not end of 2 measure and 3:1,0 should be. velocity: Note velocity (0-127, default: 96) relative_start: If True, start_time/start_measure are interpreted as offsets from the item's start (i.e. relative to item.start). If False (default), they are treated as absolute project positions.

Inputs: item (required), pitch (required), track_index (required), velocity, +5 more. Returns: result

add_midi_notesA

Add multiple MIDI notes to a MIDI item in one operation.

Important: Please check MIDI item length in which you want to add notes. If any note extends beyond the item bounds, create another one or resize existing before note adding.

Item Identification - TWO ways to specify which item:

  1. Using track_pos_idx (integer):

    • Simple position number: 0 = first item, 1 = second item, etc.

    • Get this from create_midi_item response field "track_pos_idx"

    • Quick but may become invalid if items are deleted/reordered

  2. Using direct_item_id (string):

    • REAPER's internal pointer like "MediaItem*0x000001234567890A"

    • Get this from create_midi_item response field "direct_item_id"

    • Or from get_items_in_time_range response

    • Guaranteed to always point to the same item

Recommendation: Use track_pos_idx for quick scripts, direct_item_id for reliability.

Args: track_index: Index of the track track_pos_idx: EITHER integer track_pos_idx OR string direct_item_id notes: List of note definitions, each containing: - pitch: MIDI note pitch (0-127) - start_time: Start position in seconds (optional if start_measure provided) - start_measure: Start position as "measure:beat,fraction" (optional if start_time provided) - length_time: Duration in seconds (optional if length_measure provided) - length_measure: Duration as "measure:beat,fraction" (e.g., "0:2,000" = 2 beats) - velocity: Note velocity (0-127, optional, default: 96) - relative_start: Default mode for all notes. Per-note override supported via note['relative_start'] (bool).

Example: notes = [ { "pitch": 60, "start_measure": "1:1,000", "length_measure": "0:2,000", "velocity": 100 }, { "pitch": 64, "start_time": 2.5, "length_time": 0.5 } ]

Inputs: item (required), notes (required), track_index (required), relative_start. Returns: result

clear_midi_itemB

Clear all MIDI notes from a MIDI item.

Inputs: item_id (required), track_index (required). Returns: result

create_markerC

Create a marker in the project.

Inputs: name (required), time (required). Returns: result

create_midi_itemA

Create an empty MIDI item on a track.

Important: It is recommended to avoid overlapping MIDI items. Ensure to double-check before creating a new one.

Returns both track_pos_idx and direct_item_id for flexible item referencing:

  • track_pos_idx: 0-based position index within the track (0, 1, 2, etc.)

  • direct_item_id: REAPER's internal item ID (string pointer)

Both can be used interchangeably in subsequent operations like add_midi_note.

Args: track_index: 0-based track index (0 = first track, 1 = second, etc.) Note: REAPER UI shows "Track 1, Track 2" but API uses 0, 1, etc. start_time: Start position in seconds (optional if start_measure is provided) start_measure: Start position as "measure:beat,fraction" (optional if start_time is provided) where fraction is milliseconds (e.g., "1:1,500" = measure 1, beat 1, half beat) length_time: Duration in seconds from start position (from start_time or start_measure)(optional if length_measure is provided). length_measure: Duration as "measure:beat,fraction" from start position (e.g., "2:1,000" = 2 measures from start_time or start_measure)(optional if length_time is provided). The range starts from 0:1,0. The value 0:4,0 equals three beats in a 4/4 time signature. Thus, if you want the length of all beats from one measure, then use 1:1,0; for two measures, use 2:1,0; and for three, use 3:1,0.

Inputs: track_index (required), start_time, length_time, start_measure, +1 more. Returns: result

create_regionA

Create a region in the project.

Args: name: Name of the region start_time: Start position in seconds (optional if start_measure is provided) end_time: End position in seconds (optional if end_measure is provided) start_measure: Start position as "measure:beat,fraction" (optional if start_time is provided) end_measure: End position as "measure:beat,fraction" (optional if end_time is provided)

Inputs: name (required), end_time, start_time, end_measure, +1 more. Returns: result

create_trackD

Note: Track indices in REAPER API are 0-based (first track = 0, second = 1, etc.) However, REAPER's visual interface displays tracks starting from 1. So track 0 in API = Track 1 in REAPER UI.

Inputs: name. Returns: result

delete_itemA

Delete a media item from a track.

Item Identification - Accepts BOTH types:

  • track_pos_idx (integer): Simple index like 0, 1, 2

  • direct_item_id (string): Internal ID like "MediaItem*0x..."

Args: track_index: Index of the track item: EITHER integer track_pos_idx OR string direct_item_id

Inputs: item (required), track_index (required). Returns: result

delete_markerC

Delete a marker from the project.

Inputs: marker_index (required). Returns: result

delete_regionC

Delete a region from the project.

Inputs: region_index (required). Returns: result

duplicate_itemA

Duplicate an existing item on a track.

Item Identification - Accepts BOTH types:

  • track_pos_idx (integer): Simple index like 0, 1, 2

  • direct_item_id (string): Internal ID like "MediaItem*0x..."

Args: track_index: Index of the track item_id: EITHER integer track_pos_idx OR string direct_item_id new_time: New position in seconds (optional) new_measure: New position as "measure:beat,fraction" (optional)

Inputs: item_id (required), track_index (required), new_time, new_measure. Returns: result

find_midi_notes_by_pitchA

Find all MIDI notes within a specific pitch range across the project.

Inputs: pitch_max, pitch_min. Returns: result

get_available_fx_listB

Get a list of all available FX plugins in Reaper.

Inputs: no named parameters. Returns: result

get_fx_listB

Get a list of all FX on a track.

Inputs: track_index (required). Returns: result

get_fx_paramC

Get an FX parameter value.

Inputs: fx_index (required), param_name (required), track_index (required). Returns: result

get_fx_param_listC

Get a list of all parameters for an FX.

Inputs: fx_index (required), track_index (required). Returns: result

get_item_propertiesB

Get properties of a media item.

Item Identification - Accepts BOTH types:

  • track_pos_idx (integer): Simple index like 0, 1, 2

  • direct_item_id (string): Internal ID like "MediaItem*0x..."

Args: track_index: Index of the track item_id: EITHER integer track_pos_idx OR string direct_item_id

Inputs: item (required), track_index (required). Returns: result

get_items_in_time_rangeA

Get all items on a track within a time range.

Returns items with BOTH identification methods for each item:

  1. track_pos_idx (integer):

    • Simple sequential index: 0, 1, 2, 3...

    • Easy to use in loops and quick operations

    • Changes if items before it are deleted

  2. direct_item_id (string):

    • REAPER's permanent internal ID like "MediaItem*0x..."

    • Unique stable reference that never changes

    • Use this for reliable long-term item tracking

You can use either one in subsequent operations like add_midi_note.

Args: track_index: 0-based track index (0 = first track, 1 = second, etc.) start_time: Start position in seconds (optional if start_measure is provided) end_time: End position in seconds (optional if end_measure is provided) start_measure: Start position as "measure:beat,fraction" (optional if start_time is provided) end_measure: End position as "measure:beat,fraction" (optional if end_time is provided)

Returns: Each item includes: - track_pos_idx: Integer position index (0, 1, 2...) - direct_item_id: String internal ID ("MediaItem*...") - position: Item start time in seconds - length: Item duration in seconds

Inputs: track_index (required), end_time, start_time, end_measure, +1 more. Returns: result

get_master_trackB

Get information about the master track.

Inputs: no named parameters. Returns: result

get_midi_notesA

Get all MIDI notes from a MIDI item.

By default, returns only visible notes (within item bounds). Invisible notes exist in the MIDI data but won't sound during playback.

Item Identification - Accepts BOTH types:

  • track_pos_idx (integer): Simple index like 0, 1, 2

  • direct_item_id (string): Internal ID like "MediaItem*0x..."

Args: track_index: Index of the track item_id: EITHER integer track_pos_idx OR string direct_item_id include_invisible: If True, include notes outside item bounds (won't sound). Default: False

Inputs: item_id (required), track_index (required), include_invisible. Returns: result

get_project_time_signatureB

Get the default project time signature.

Inputs: no named parameters. Returns: result

get_region_listA

Get a list of all regions in the project.

Returns: Dict containing status and a list of regions, each with: - index: region index - start: region start position - end: region end position

Inputs: no named parameters. Returns: result

get_selected_itemsA

Get all selected media items in the project with their properties.

Returns: Dict containing status and list of selected items with their properties: - track_index: Index of the track containing the item - item_index: Index of the item in its track - position: Start time in seconds - length: Length in seconds from the start of item - is_midi: Whether the item is a MIDI item - name: Item name if available

Inputs: no named parameters. Returns: result

get_selected_midi_itemA

Get the first selected MIDI item in the project.

Inputs: no named parameters. Returns: result

get_tempoA

Get the current project tempo.

Inputs: no named parameters. Returns: result

get_time_signatureA

Get the current time signature of the project.

Inputs: no named parameters. Returns: result

get_track_colorA

Get the color of a track.

Args: track_index: 0-based track index (0 = first track, 1 = second track, etc.)

Inputs: track_index (required). Returns: result

get_track_countA

Get the number of tracks in the project.

Inputs: no named parameters. Returns: result

get_track_listA

Get a list of all tracks in the project.

Returns: Dict containing status and a list of tracks, each with: - index: Track index - name: Track name - color: Track color (if available)

Inputs: no named parameters. Returns: result

insert_audio_itemA

Insert an audio file as a media item on a track.

Args: track_index: Index of the track file_path: Path to the audio file start_time: Start position in seconds (optional if start_measure is provided) start_measure: Start position as "measure:beat,fraction" (optional if start_time is provided)

Inputs: file_path (required), track_index (required), start_time, start_measure. Returns: result

remove_fxB

Remove an FX from a track.

Inputs: fx_index (required), track_index (required). Returns: result

rename_trackA

Rename an existing track.

Args: track_index: 0-based track index (0 = first track, 1 = second, etc.) Note: REAPER UI shows tracks starting from 1, but API uses 0-based indexing. API track 0 = UI Track 1, API track 1 = UI Track 2, etc. new_name: New name for the track

Inputs: new_name (required), track_index (required). Returns: result

render_projectA

Render project to audio file.

Args: output_file: Path to output audio file start_time: Start position in seconds (optional if start_measure is provided) end_time: End position in seconds (optional if end_measure is provided) start_measure: Start position as "measure:beat,fraction" (optional if start_time is provided) end_measure: End position as "measure:beat,fraction" (optional if end_time is provided) samplerate: Sample rate in Hz (default: 44100) channels: Number of channels (default: 2) file_format: Formats available on this machine "wave" "aiff" "iso " "ddp " "flac" "mp3l" "oggv" "OggS" "FFMP" "GIF " "LCF " "wvpk"

Inputs: output_file (required), channels, end_time, samplerate, +4 more. Returns: result

set_fx_paramC

Set an FX parameter value.

Inputs: value (required), fx_index (required), param_name (required), track_index (required). Returns: result

set_item_lengthA

Set the length of a media item.

Item Identification - Accepts BOTH types:

  • track_pos_idx (integer): Simple index like 0, 1, 2

  • direct_item_id (string): Internal ID like "MediaItem*0x..."

Args: track_index: Index of the track item_id: EITHER integer track_pos_idx OR string direct_item_id length_time: Length in seconds from start of item (optional if length_measure is provided) length_measure: Length as "measure:beat,fraction" from start of item(optional if length_time is provided)

Inputs: item_id (required), track_index (required), length_time, length_measure. Returns: result

set_item_positionA

Set the position of a media item.

Item Identification - Accepts BOTH types:

  • track_pos_idx (integer): Simple index like 0, 1, 2

  • direct_item_id (string): Internal ID like "MediaItem*0x..."

Args: track_index: Index of the track item_id: EITHER integer track_pos_idx OR string direct_item_id position_time: New position in seconds (optional if position_measure is provided) position_measure: New position as "measure:beat,fraction" (optional if position_time is provided) where fraction is milliseconds (e.g., "1:1,500" = measure 1, beat 1, half beat)

Inputs: item_id (required), track_index (required), position_time, position_measure. Returns: result

set_master_panC

Set the master track pan.

Inputs: pan (required). Returns: result

set_master_volumeB

Set the master track volume.

Inputs: volume (required). Returns: result

set_project_time_signatureB

Set the default project time signature.

Args: numerator: Time signature numerator (e.g., 4 in 4/4) denominator: Time signature denominator (e.g., 4 in 4/4)

Inputs: numerator (required), denominator (required). Returns: result

set_tempoC

Set the project tempo.

Inputs: bpm (required). Returns: result

set_time_signatureA

Set time signature at specified position.

Args: numerator: Time signature numerator (e.g., 4 in 4/4) denominator: Time signature denominator (e.g., 4 in 4/4) position: Position as "measure:beat,fraction" (optional if time is provided) where fraction is milliseconds (e.g., "1:1,500" = measure 1, beat 1, half beat) time: Position in seconds (optional if position is provided)

Inputs: numerator (required), denominator (required), time, position. Returns: result

set_track_colorB

Set the color of a track.

Args: track_index: 0-based track index (0 = first track, 1 = second track, etc.) color: Color value

Inputs: color (required), track_index (required). Returns: result

test_connectionA

Test connection to Reaper.

Inputs: no named parameters. Returns: result

toggle_fxB

Toggle or set the enable/disable state of an FX.

Inputs: fx_index (required), track_index (required), enable. Returns: result

toggle_master_muteA

Toggle or set the master track mute state.

Inputs: mute. Returns: result

toggle_master_soloB

Toggle or set the master track solo state.

Inputs: solo. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.7/5.0

    Scored across 47 tools

    Disambiguation2/5

    Several tools have unclear boundaries, especially the time signature cluster (get_time_signature, get_project_time_signature, set_project_time_signature, set_time_signature) which appear to overlap. get_selected_midi_item and get_selected_items also partially overlap, leading to potential misselection.

    Naming Consistency5/5

    All tool names follow a strict verb_noun snake_case pattern (e.g., create_track, set_tempo, get_midi_notes). There are no mixed conventions or vague verbs, making the naming predictable and self-documenting.

    Tool Count2/5

    With 47 tools, the server is far above the typical well-scoped range. While REAPER is a complex DAW, this count feels excessive and likely overwhelms agents, especially with many specialized query and manipulation tools.

    Completeness2/5

    Core DAW operations are missing: no delete_track, no per-track volume/pan/mute/solo controls, and no get_marker_list. These gaps force agents to use workarounds or fail when performing basic track management and marker retrieval.

    Maintenance

    ActivityInactive
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A Model Context Protocol server that exposes REAPER digital audio workstation functionality through a clean API interface, enabling programmatic control of 169+ REAPER operations across track management, MIDI editing, effects, automation and more.
      89
      MIT
    • A
      license
      B
      quality
      A
      maintenance
      Connects AI assistants to REAPER for music production, enabling full control over tracks, MIDI, mixing, mastering, and audio analysis through 153 tools across 24 modules.
      174
      117
      Apache 2.0
    • A
      license
      B
      quality
      D
      maintenance
      This MCP server enables AI assistants to control a live REAPER DAW instance, including transport, tracks, FX, MIDI, media, markers, rendering, and project state, with an escape hatch for arbitrary ReaScript commands.
      40
      MIT