reaper-reapy-mcp
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-reapy-mcp create a new track called 'Drums'"
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 and MCP or AI integration
A Python application for controlling REAPER Digital Audio Workstation (DAW) using the MCP(Model context protocol).


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-reapyPython modulemcp[cli]package for MCP serverInternet connection (for downloading sample audio file)
Installation
Install REAPER if you haven't already
Enable reapy server via REAPER scripting add reaper_side_enable_server.py to reaper actions and run it inside reaper studio
Install the package:
# From PyPI pip install reaper_reapy_mcp # From GitHub repository pip install git+https://github.com/wegitor/reaper-reapy-mcp.gitEnable 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.mp3This 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_mcpFor the current directory and http MCP mode:
uv --directory . run -m reaper_reapy_mcp --mode httpFor example, on Windows:
uv --directory C:\path\to\reaper_reapy_mcp run -m reaper_reapy_mcpOr using the Python module directly after installation:
python -m reaper_reapy_mcpHTTP Mode
Run the server in HTTP mode with default settings:
python -m reaper_reapy_mcp --mode httpRun with custom host and port:
python -m reaper_reapy_mcp --mode http --http-host example_host --http-port 3958Use the MCP inspector to test the tools:
test_mcp.batAvailable MCP tools:
Track Management
test_connection: Verify connection to REAPERcreate_track: Create a new trackrename_track: Rename an existing trackset_track_color: Set track colorget_track_color: Get track colorget_track_count: Get number of tracks in projectget_track_list: Get list of all tracks with their properties
FX Management
add_fx: Add an FX to a trackremove_fx: Remove an FX from a trackset_fx_param: Set FX parameter valueget_fx_param: Get FX parameter valueget_fx_param_list: Get list of FX parametersget_fx_list: Get list of FX on a trackget_available_fx_list: Get list of available FX pluginstoggle_fx: Toggle FX enable/disable state
Project Control
set_tempo: Set project tempoget_tempo: Get current tempoget_time_signature: Get current time signatureset_project_time_signature: Set project default time signatureset_time_signature: Set time signature at positioncreate_region: Create a regiondelete_region: Delete a regioncreate_marker: Create a markerdelete_marker: Delete a markerrender_project: Render project to audio file
Master Track
get_master_track: Get master track informationset_master_volume: Set master track volumeset_master_pan: Set master track pantoggle_master_mute: Toggle master track mutetoggle_master_solo: Toggle master track solo
MIDI Operations
create_midi_item: Create an empty MIDI item on a trackSupports both time (seconds) and measure:beat positioning
add_midi_note: Add a MIDI note to a MIDI itemadd_midi_notes: Add multiple MIDI notes at onceget_midi_notes: Get all MIDI notes from a MIDI itemclear_midi_item: Clear all MIDI notes from a MIDI item
Audio Item Operations
insert_audio_item: Insert an audio file as a media itemSupports 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 itemset_item_position: Set the position of a media itemSupports both time (seconds) and measure:beat positioning
set_item_length: Set the length of a media itemdelete_item: Delete a media itemget_items_in_time_range: Get items within a time rangeSupports 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 numberbeat: 1-based beat numberfraction: milliseconds (000-999) representing fraction of a beatExample:
"4:2,500"= measure 4, beat 2, half beat (500ms)
Tools Supporting Both Formats:
create_midi_item- position viastart_timeORstart_measureinsert_audio_item- position viastart_timeORstart_measureduplicate_item- position vianew_timeORnew_measureset_item_position- position vianew_timeORnew_measureget_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 toolsadd_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:
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
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:
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
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:
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
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
Scored across 47 tools
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.
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.
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.
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
Related MCP Connectors
Remote MCP server for audio stem separation, denoise, reverb, and MIDI export.
Compose, mix, master and export in Logic Pro, REAPER or Ableton Live by talking to an AI engineer.
Read and edit DAW projects as an agent, save native Logic projects, convert projects between DAWs
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA 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.89MIT
- AlicenseBqualityAmaintenanceConnects AI assistants to REAPER for music production, enabling full control over tracks, MIDI, mixing, mastering, and audio analysis through 153 tools across 24 modules.174117Apache 2.0
- 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-
- AlicenseBqualityDmaintenanceThis 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.40MIT