reaper-mcp-server 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reaper_mcp_server-0.1.0/.gitignore +40 -0
- reaper_mcp_server-0.1.0/LICENSE +21 -0
- reaper_mcp_server-0.1.0/PKG-INFO +142 -0
- reaper_mcp_server-0.1.0/README.md +114 -0
- reaper_mcp_server-0.1.0/config.json +11 -0
- reaper_mcp_server-0.1.0/custom_mcp_server.py +110 -0
- reaper_mcp_server-0.1.0/examples/create_drum_kit_actions.py +81 -0
- reaper_mcp_server-0.1.0/examples/create_drum_pattern.py +80 -0
- reaper_mcp_server-0.1.0/examples/create_tracks_fixed.py +52 -0
- reaper_mcp_server-0.1.0/examples/test_mcp_tools.py +102 -0
- reaper_mcp_server-0.1.0/examples/test_osc_mcp.py +51 -0
- reaper_mcp_server-0.1.0/http_server.py +134 -0
- reaper_mcp_server-0.1.0/osc_mcp_server.py +256 -0
- reaper_mcp_server-0.1.0/pyproject.toml +52 -0
- reaper_mcp_server-0.1.0/run_http_server.py +23 -0
- reaper_mcp_server-0.1.0/scripts/enable_reapy.py +33 -0
- reaper_mcp_server-0.1.0/scripts/setup_reaper_osc.py +45 -0
- reaper_mcp_server-0.1.0/scripts/setup_reaper_python.py +35 -0
- reaper_mcp_server-0.1.0/scripts/start_reaper_mcp_server.bat +66 -0
- reaper_mcp_server-0.1.0/scripts/start_reaper_mcp_server.ps1 +56 -0
- reaper_mcp_server-0.1.0/scripts/start_reaper_mcp_server.sh +69 -0
- reaper_mcp_server-0.1.0/simple_mcp_server.py +67 -0
- reaper_mcp_server-0.1.0/smithery.yaml +14 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/__init__.py +1 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/__main__.py +23 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/analysis_tools.py +224 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/audio_tools.py +170 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/config.py +44 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/connection.py +29 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/fx_tools.py +155 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/mastering_tools.py +201 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/midi_tools.py +233 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/mixing_tools.py +160 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/project_tools.py +126 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/render_tools.py +183 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/server.py +28 -0
- reaper_mcp_server-0.1.0/src/reaper_mcp/track_tools.py +176 -0
- reaper_mcp_server-0.1.0/start_osc_mcp.sh +19 -0
- reaper_mcp_server-0.1.0/start_reaper_mcp.sh +19 -0
- reaper_mcp_server-0.1.0/windsurf_mcp_server.py +110 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual Environment
|
|
24
|
+
venv/
|
|
25
|
+
ENV/
|
|
26
|
+
env/
|
|
27
|
+
|
|
28
|
+
# IDE files
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
|
|
34
|
+
# OS specific files
|
|
35
|
+
.DS_Store
|
|
36
|
+
Thumbs.db
|
|
37
|
+
|
|
38
|
+
# REAPER specific
|
|
39
|
+
*.RPP-bak
|
|
40
|
+
*.reapeaks
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Youssef Hemimy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reaper-mcp-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for controlling REAPER DAW with AI agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/bonfire-audio/reaper-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/bonfire-audio/reaper-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/bonfire-audio/reaper-mcp/issues
|
|
8
|
+
Author-email: Youssef Hemimy <itsuzef@users.noreply.github.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: audio,daw,mastering,mcp,midi,mixing,music,reaper
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: librosa>=0.10.0
|
|
18
|
+
Requires-Dist: mcp>=1.0.0
|
|
19
|
+
Requires-Dist: numpy>=1.24.0
|
|
20
|
+
Requires-Dist: platformdirs>=3.0.0
|
|
21
|
+
Requires-Dist: pyloudnorm>=0.1.1
|
|
22
|
+
Requires-Dist: python-reapy>=0.10.0
|
|
23
|
+
Requires-Dist: soundfile>=0.12.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# REAPER MCP Server
|
|
30
|
+
|
|
31
|
+
A Model Context Protocol (MCP) server that enables AI agents to control REAPER DAW — 58 tools covering project management, tracks, MIDI, FX, mixing, mastering, rendering, and audio analysis.
|
|
32
|
+
|
|
33
|
+
## Requirements
|
|
34
|
+
|
|
35
|
+
- [REAPER](https://www.reaper.fm/) DAW installed and running
|
|
36
|
+
- Python 3.10+
|
|
37
|
+
- REAPER's distant API enabled (see [Setup](#setting-up-reaper))
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install reaper-mcp-server
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or install from source:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/bonfire-audio/reaper-mcp.git
|
|
49
|
+
cd reaper-mcp
|
|
50
|
+
pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Setting Up REAPER
|
|
54
|
+
|
|
55
|
+
The server communicates with REAPER via [python-reapy](https://github.com/RomeoDespres/reapy), which requires REAPER's distant API to be enabled.
|
|
56
|
+
|
|
57
|
+
### Option 1: Run the setup script
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python scripts/enable_reapy.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Option 2: Manual setup
|
|
64
|
+
|
|
65
|
+
1. Open REAPER
|
|
66
|
+
2. Go to Actions > Run ReaScript
|
|
67
|
+
3. Run this Python code:
|
|
68
|
+
```python
|
|
69
|
+
import reapy
|
|
70
|
+
reapy.config.enable_dist_api()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
### With Claude Desktop
|
|
76
|
+
|
|
77
|
+
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"mcpServers": {
|
|
82
|
+
"reaper": {
|
|
83
|
+
"command": "reaper-mcp-server",
|
|
84
|
+
"args": []
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### With Claude Code
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
claude mcp add reaper -- reaper-mcp-server
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Standalone
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
reaper-mcp-server # start the server
|
|
100
|
+
reaper-mcp-server --debug # with debug logging
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Tools (58)
|
|
104
|
+
|
|
105
|
+
### Project Management
|
|
106
|
+
`create_project` `load_project` `save_project` `get_project_info` `set_tempo` `set_time_signature` `set_cursor_position` `play_project` `stop_transport`
|
|
107
|
+
|
|
108
|
+
### Tracks
|
|
109
|
+
`create_track` `delete_track` `rename_track` `list_tracks` `get_track_info` `set_track_color` `create_bus` `create_send` `remove_send` `list_sends`
|
|
110
|
+
|
|
111
|
+
### MIDI
|
|
112
|
+
`create_midi_item` `add_midi_note` `create_chord_progression` `create_drum_pattern`
|
|
113
|
+
|
|
114
|
+
### FX & Instruments
|
|
115
|
+
`add_fx` `remove_fx` `bypass_fx` `list_track_fx` `get_fx_parameters` `set_fx_parameter` `load_fx_preset` `add_master_fx` `list_master_fx` `set_master_fx_parameter`
|
|
116
|
+
|
|
117
|
+
### Audio
|
|
118
|
+
`import_audio_file` `edit_audio_item` `start_recording` `adjust_pitch` `adjust_playback_rate`
|
|
119
|
+
|
|
120
|
+
### Mixing
|
|
121
|
+
`set_track_volume` `set_track_pan` `set_track_mute` `set_track_solo` `set_send_volume` `set_master_volume` `add_volume_automation` `add_pan_automation`
|
|
122
|
+
|
|
123
|
+
### Rendering
|
|
124
|
+
`render_project` `render_stems` `render_time_selection`
|
|
125
|
+
|
|
126
|
+
### Mastering
|
|
127
|
+
`apply_mastering_chain` `apply_limiter` `normalize_project`
|
|
128
|
+
|
|
129
|
+
### Analysis
|
|
130
|
+
`analyze_loudness` `analyze_dynamics` `analyze_frequency_spectrum` `analyze_stereo_field` `analyze_transients` `detect_clipping`
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
The server stores its configuration in your platform's config directory:
|
|
135
|
+
|
|
136
|
+
- macOS: `~/Library/Application Support/reaper-mcp/config.json`
|
|
137
|
+
- Linux: `~/.config/reaper-mcp/config.json`
|
|
138
|
+
- Windows: `%APPDATA%\reaper-mcp\config.json`
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# REAPER MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server that enables AI agents to control REAPER DAW — 58 tools covering project management, tracks, MIDI, FX, mixing, mastering, rendering, and audio analysis.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- [REAPER](https://www.reaper.fm/) DAW installed and running
|
|
8
|
+
- Python 3.10+
|
|
9
|
+
- REAPER's distant API enabled (see [Setup](#setting-up-reaper))
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install reaper-mcp-server
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or install from source:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/bonfire-audio/reaper-mcp.git
|
|
21
|
+
cd reaper-mcp
|
|
22
|
+
pip install -e .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Setting Up REAPER
|
|
26
|
+
|
|
27
|
+
The server communicates with REAPER via [python-reapy](https://github.com/RomeoDespres/reapy), which requires REAPER's distant API to be enabled.
|
|
28
|
+
|
|
29
|
+
### Option 1: Run the setup script
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python scripts/enable_reapy.py
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Option 2: Manual setup
|
|
36
|
+
|
|
37
|
+
1. Open REAPER
|
|
38
|
+
2. Go to Actions > Run ReaScript
|
|
39
|
+
3. Run this Python code:
|
|
40
|
+
```python
|
|
41
|
+
import reapy
|
|
42
|
+
reapy.config.enable_dist_api()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### With Claude Desktop
|
|
48
|
+
|
|
49
|
+
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"reaper": {
|
|
55
|
+
"command": "reaper-mcp-server",
|
|
56
|
+
"args": []
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### With Claude Code
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
claude mcp add reaper -- reaper-mcp-server
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Standalone
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
reaper-mcp-server # start the server
|
|
72
|
+
reaper-mcp-server --debug # with debug logging
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Tools (58)
|
|
76
|
+
|
|
77
|
+
### Project Management
|
|
78
|
+
`create_project` `load_project` `save_project` `get_project_info` `set_tempo` `set_time_signature` `set_cursor_position` `play_project` `stop_transport`
|
|
79
|
+
|
|
80
|
+
### Tracks
|
|
81
|
+
`create_track` `delete_track` `rename_track` `list_tracks` `get_track_info` `set_track_color` `create_bus` `create_send` `remove_send` `list_sends`
|
|
82
|
+
|
|
83
|
+
### MIDI
|
|
84
|
+
`create_midi_item` `add_midi_note` `create_chord_progression` `create_drum_pattern`
|
|
85
|
+
|
|
86
|
+
### FX & Instruments
|
|
87
|
+
`add_fx` `remove_fx` `bypass_fx` `list_track_fx` `get_fx_parameters` `set_fx_parameter` `load_fx_preset` `add_master_fx` `list_master_fx` `set_master_fx_parameter`
|
|
88
|
+
|
|
89
|
+
### Audio
|
|
90
|
+
`import_audio_file` `edit_audio_item` `start_recording` `adjust_pitch` `adjust_playback_rate`
|
|
91
|
+
|
|
92
|
+
### Mixing
|
|
93
|
+
`set_track_volume` `set_track_pan` `set_track_mute` `set_track_solo` `set_send_volume` `set_master_volume` `add_volume_automation` `add_pan_automation`
|
|
94
|
+
|
|
95
|
+
### Rendering
|
|
96
|
+
`render_project` `render_stems` `render_time_selection`
|
|
97
|
+
|
|
98
|
+
### Mastering
|
|
99
|
+
`apply_mastering_chain` `apply_limiter` `normalize_project`
|
|
100
|
+
|
|
101
|
+
### Analysis
|
|
102
|
+
`analyze_loudness` `analyze_dynamics` `analyze_frequency_spectrum` `analyze_stereo_field` `analyze_transients` `detect_clipping`
|
|
103
|
+
|
|
104
|
+
## Configuration
|
|
105
|
+
|
|
106
|
+
The server stores its configuration in your platform's config directory:
|
|
107
|
+
|
|
108
|
+
- macOS: `~/Library/Application Support/reaper-mcp/config.json`
|
|
109
|
+
- Linux: `~/.config/reaper-mcp/config.json`
|
|
110
|
+
- Windows: `%APPDATA%\reaper-mcp\config.json`
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reaper_path": "/Applications/REAPER.app",
|
|
3
|
+
"default_project_directory": "/Users/youssefhemimy/Documents/REAPER Projects",
|
|
4
|
+
"vst_directories": ["/Library/Audio/Plug-Ins/VST", "/Library/Audio/Plug-Ins/VST3"],
|
|
5
|
+
"sample_libraries": ["/Volumes/ExtremeSSD/Soundbanks/SB_October"],
|
|
6
|
+
"default_tempo": 120.0,
|
|
7
|
+
"default_time_signature": "4/4",
|
|
8
|
+
"default_sample_rate": 48000,
|
|
9
|
+
"default_bit_depth": 24,
|
|
10
|
+
"default_audio_format": "wav"
|
|
11
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Custom MCP Server for REAPER
|
|
4
|
+
This script provides a robust MCP server implementation that should work with IDE integration
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
import os
|
|
10
|
+
import reapy
|
|
11
|
+
from mcp.server.fastmcp import FastMCP
|
|
12
|
+
import logging
|
|
13
|
+
|
|
14
|
+
# Set up logging
|
|
15
|
+
logging.basicConfig(level=logging.DEBUG,
|
|
16
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
17
|
+
stream=sys.stderr)
|
|
18
|
+
logger = logging.getLogger("reaper-mcp")
|
|
19
|
+
|
|
20
|
+
# Create the MCP server
|
|
21
|
+
mcp = FastMCP("ReaperMCP")
|
|
22
|
+
|
|
23
|
+
# Connect to REAPER
|
|
24
|
+
try:
|
|
25
|
+
logger.info("Attempting to connect to REAPER...")
|
|
26
|
+
reapy.connect()
|
|
27
|
+
logger.info("Successfully connected to REAPER")
|
|
28
|
+
except Exception as e:
|
|
29
|
+
logger.error(f"Failed to connect to REAPER: {e}")
|
|
30
|
+
logger.error("Make sure REAPER is running with ReaScript API enabled")
|
|
31
|
+
sys.exit(1)
|
|
32
|
+
|
|
33
|
+
# Simple tool definitions
|
|
34
|
+
@mcp.tool()
|
|
35
|
+
def create_project(name, template=None):
|
|
36
|
+
"""Creates a new REAPER project."""
|
|
37
|
+
try:
|
|
38
|
+
project = reapy.Project()
|
|
39
|
+
if name:
|
|
40
|
+
project.save(os.path.join(os.path.expanduser("~/Documents/REAPER Projects"), f"{name}.rpp"))
|
|
41
|
+
return {"success": True, "message": f"Created project: {name}"}
|
|
42
|
+
except Exception as e:
|
|
43
|
+
logger.error(f"Error creating project: {e}")
|
|
44
|
+
return {"success": False, "error": str(e)}
|
|
45
|
+
|
|
46
|
+
@mcp.tool()
|
|
47
|
+
def create_track(name=None):
|
|
48
|
+
"""Creates a new track in the current project."""
|
|
49
|
+
try:
|
|
50
|
+
project = reapy.Project()
|
|
51
|
+
track = project.add_track(index=project.n_tracks, name=name)
|
|
52
|
+
return {"success": True, "track_index": track.index}
|
|
53
|
+
except Exception as e:
|
|
54
|
+
logger.error(f"Error creating track: {e}")
|
|
55
|
+
return {"success": False, "error": str(e)}
|
|
56
|
+
|
|
57
|
+
@mcp.tool()
|
|
58
|
+
def list_tracks():
|
|
59
|
+
"""Lists all tracks in the current project."""
|
|
60
|
+
try:
|
|
61
|
+
project = reapy.Project()
|
|
62
|
+
tracks = []
|
|
63
|
+
for i in range(project.n_tracks):
|
|
64
|
+
track = project.tracks[i]
|
|
65
|
+
tracks.append({
|
|
66
|
+
"index": i,
|
|
67
|
+
"name": track.name,
|
|
68
|
+
"is_selected": track.is_selected
|
|
69
|
+
})
|
|
70
|
+
return {"success": True, "tracks": tracks}
|
|
71
|
+
except Exception as e:
|
|
72
|
+
logger.error(f"Error listing tracks: {e}")
|
|
73
|
+
return {"success": False, "error": str(e)}
|
|
74
|
+
|
|
75
|
+
@mcp.tool()
|
|
76
|
+
def add_midi_note(track_index, note, start_time, duration, velocity=100):
|
|
77
|
+
"""Adds a MIDI note to a track."""
|
|
78
|
+
try:
|
|
79
|
+
project = reapy.Project()
|
|
80
|
+
track = project.tracks[track_index]
|
|
81
|
+
item = track.add_item(start=start_time, length=duration)
|
|
82
|
+
take = item.add_take()
|
|
83
|
+
take.add_note(note=note, start=0, end=duration, velocity=velocity)
|
|
84
|
+
return {"success": True, "message": f"Added note {note} to track {track_index}"}
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logger.error(f"Error adding MIDI note: {e}")
|
|
87
|
+
return {"success": False, "error": str(e)}
|
|
88
|
+
|
|
89
|
+
@mcp.tool()
|
|
90
|
+
def get_project_info():
|
|
91
|
+
"""Gets information about the current project."""
|
|
92
|
+
try:
|
|
93
|
+
project = reapy.Project()
|
|
94
|
+
return {
|
|
95
|
+
"success": True,
|
|
96
|
+
"name": project.name,
|
|
97
|
+
"path": project.path,
|
|
98
|
+
"length": project.length,
|
|
99
|
+
"track_count": project.n_tracks,
|
|
100
|
+
"selected_track_count": project.n_selected_tracks
|
|
101
|
+
}
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logger.error(f"Error getting project info: {e}")
|
|
104
|
+
return {"success": False, "error": str(e)}
|
|
105
|
+
|
|
106
|
+
# Run the server
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
logger.info("Starting custom REAPER MCP Server...")
|
|
109
|
+
# Use stdio transport for MCP protocol
|
|
110
|
+
mcp.run(transport='stdio')
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Create a drum kit in REAPER using OSC action IDs
|
|
4
|
+
This script uses REAPER's specific action IDs to create tracks properly
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from pythonosc import udp_client
|
|
10
|
+
|
|
11
|
+
# OSC settings (matching our server configuration)
|
|
12
|
+
REAPER_OSC_HOST = "192.168.1.110"
|
|
13
|
+
REAPER_OSC_PORT = 8000
|
|
14
|
+
|
|
15
|
+
# REAPER Action IDs
|
|
16
|
+
ACTION_NEW_PROJECT = 40023
|
|
17
|
+
ACTION_INSERT_TRACK = 40001
|
|
18
|
+
ACTION_SELECT_TRACK_1 = 40939
|
|
19
|
+
ACTION_SELECT_TRACK_2 = 40940
|
|
20
|
+
ACTION_SELECT_TRACK_3 = 40941
|
|
21
|
+
ACTION_SELECT_TRACK_4 = 40942
|
|
22
|
+
ACTION_INSERT_MIDI_ITEM = 40214
|
|
23
|
+
ACTION_SET_TEMPO = 40364
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
print("Creating a drum kit in REAPER using action IDs...")
|
|
27
|
+
|
|
28
|
+
# Create OSC client
|
|
29
|
+
client = udp_client.SimpleUDPClient(REAPER_OSC_HOST, REAPER_OSC_PORT)
|
|
30
|
+
|
|
31
|
+
# Create a new project
|
|
32
|
+
print("Creating a new project...")
|
|
33
|
+
client.send_message("/action", [ACTION_NEW_PROJECT])
|
|
34
|
+
time.sleep(1.5)
|
|
35
|
+
|
|
36
|
+
# Create drum tracks (we need to create 4 tracks)
|
|
37
|
+
track_names = ["Kick", "Snare", "Hi-Hat", "Crash"]
|
|
38
|
+
|
|
39
|
+
for i, name in enumerate(track_names):
|
|
40
|
+
if i > 0: # First track already exists, create additional tracks
|
|
41
|
+
print(f"Creating track {i+1}...")
|
|
42
|
+
client.send_message("/action", [ACTION_INSERT_TRACK])
|
|
43
|
+
time.sleep(0.8)
|
|
44
|
+
|
|
45
|
+
# Select the track (track 1 is already selected after creation)
|
|
46
|
+
if i == 1:
|
|
47
|
+
client.send_message("/action", [ACTION_SELECT_TRACK_2])
|
|
48
|
+
elif i == 2:
|
|
49
|
+
client.send_message("/action", [ACTION_SELECT_TRACK_3])
|
|
50
|
+
elif i == 3:
|
|
51
|
+
client.send_message("/action", [ACTION_SELECT_TRACK_4])
|
|
52
|
+
time.sleep(0.5)
|
|
53
|
+
|
|
54
|
+
# Name the track
|
|
55
|
+
print(f"Naming track: {name}...")
|
|
56
|
+
client.send_message(f"/track/{i}/name", [name])
|
|
57
|
+
time.sleep(0.5)
|
|
58
|
+
|
|
59
|
+
# Insert MIDI item
|
|
60
|
+
print(f"Adding MIDI item to {name} track...")
|
|
61
|
+
client.send_message("/action", [ACTION_INSERT_MIDI_ITEM])
|
|
62
|
+
time.sleep(0.8)
|
|
63
|
+
|
|
64
|
+
# Set project tempo to 120 BPM
|
|
65
|
+
print("Setting project tempo to 120 BPM...")
|
|
66
|
+
# First select tempo dialog
|
|
67
|
+
client.send_message("/action", [ACTION_SET_TEMPO])
|
|
68
|
+
time.sleep(0.8)
|
|
69
|
+
# Then send the tempo value (this might not work via OSC, but worth trying)
|
|
70
|
+
client.send_message("/tempo", [120.0])
|
|
71
|
+
time.sleep(0.5)
|
|
72
|
+
|
|
73
|
+
print("\nDrum kit created with the following tracks:")
|
|
74
|
+
for name in track_names:
|
|
75
|
+
print(f"- {name}")
|
|
76
|
+
|
|
77
|
+
print("\nCheck REAPER to see if the tracks were created properly.")
|
|
78
|
+
print("You may need to manually set the tempo to 120 BPM if that didn't work via OSC.")
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
main()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Create a simple drum pattern in REAPER using OSC
|
|
4
|
+
This script demonstrates how to create a more complex musical pattern using OSC
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from pythonosc import udp_client
|
|
10
|
+
|
|
11
|
+
# OSC settings (matching our server configuration)
|
|
12
|
+
REAPER_OSC_HOST = "192.168.1.110"
|
|
13
|
+
REAPER_OSC_PORT = 8000
|
|
14
|
+
|
|
15
|
+
def main():
|
|
16
|
+
print("Creating a drum pattern in REAPER using OSC...")
|
|
17
|
+
|
|
18
|
+
# Create OSC client
|
|
19
|
+
client = udp_client.SimpleUDPClient(REAPER_OSC_HOST, REAPER_OSC_PORT)
|
|
20
|
+
|
|
21
|
+
# Create a new project
|
|
22
|
+
print("Creating a new project...")
|
|
23
|
+
client.send_message("/new", None)
|
|
24
|
+
time.sleep(1)
|
|
25
|
+
|
|
26
|
+
# Set project tempo to 120 BPM
|
|
27
|
+
print("Setting project tempo to 120 BPM...")
|
|
28
|
+
client.send_message("/tempo", [120.0])
|
|
29
|
+
time.sleep(0.5)
|
|
30
|
+
|
|
31
|
+
# Create drum tracks
|
|
32
|
+
track_names = ["Kick", "Snare", "Hi-Hat", "Crash"]
|
|
33
|
+
|
|
34
|
+
for i, name in enumerate(track_names):
|
|
35
|
+
print(f"Creating track: {name}...")
|
|
36
|
+
client.send_message("/track/add", None)
|
|
37
|
+
time.sleep(0.5)
|
|
38
|
+
client.send_message(f"/track/{i}/name", [name])
|
|
39
|
+
time.sleep(0.2)
|
|
40
|
+
|
|
41
|
+
# Create a 4-bar pattern (16 beats at 4/4)
|
|
42
|
+
print("Creating MIDI items for the pattern...")
|
|
43
|
+
|
|
44
|
+
# Pattern definitions (1 = hit, 0 = rest)
|
|
45
|
+
patterns = {
|
|
46
|
+
"Kick": [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
|
|
47
|
+
"Snare": [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],
|
|
48
|
+
"Hi-Hat": [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
|
|
49
|
+
"Crash": [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Create MIDI items for each track
|
|
53
|
+
for i, (track_name, pattern) in enumerate(patterns.items()):
|
|
54
|
+
# Select the track
|
|
55
|
+
client.send_message(f"/track/{i}/select", [1])
|
|
56
|
+
time.sleep(0.2)
|
|
57
|
+
|
|
58
|
+
# Insert a 4-bar MIDI item
|
|
59
|
+
client.send_message("/insert/midi", None)
|
|
60
|
+
time.sleep(0.5)
|
|
61
|
+
|
|
62
|
+
# We can't directly add MIDI notes via OSC
|
|
63
|
+
# But we've created the MIDI items that can be edited in REAPER
|
|
64
|
+
|
|
65
|
+
print(f"Created pattern for {track_name}")
|
|
66
|
+
|
|
67
|
+
print("\nDrum pattern created! You'll need to add the actual MIDI notes in REAPER.")
|
|
68
|
+
print("The pattern structure is:")
|
|
69
|
+
|
|
70
|
+
# Print the pattern as a visual representation
|
|
71
|
+
for name, pattern in patterns.items():
|
|
72
|
+
pattern_str = ""
|
|
73
|
+
for beat in pattern:
|
|
74
|
+
pattern_str += "X " if beat == 1 else "- "
|
|
75
|
+
print(f"{name.ljust(8)}: {pattern_str}")
|
|
76
|
+
|
|
77
|
+
print("\nYou can now open the MIDI editor in REAPER to add the notes according to this pattern.")
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
main()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Create tracks in REAPER using OSC with a different approach
|
|
4
|
+
This script tries different OSC commands to properly create new tracks
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from pythonosc import udp_client
|
|
10
|
+
|
|
11
|
+
# OSC settings (matching our server configuration)
|
|
12
|
+
REAPER_OSC_HOST = "192.168.1.110"
|
|
13
|
+
REAPER_OSC_PORT = 8000
|
|
14
|
+
|
|
15
|
+
def main():
|
|
16
|
+
print("Testing different methods to create tracks in REAPER...")
|
|
17
|
+
|
|
18
|
+
# Create OSC client
|
|
19
|
+
client = udp_client.SimpleUDPClient(REAPER_OSC_HOST, REAPER_OSC_PORT)
|
|
20
|
+
|
|
21
|
+
# Method 1: Using the specific insert track command
|
|
22
|
+
print("\nMethod 1: Using /track/insert command...")
|
|
23
|
+
client.send_message("/track/insert", None)
|
|
24
|
+
time.sleep(1)
|
|
25
|
+
client.send_message("/track/0/name", ["Method 1 Track"])
|
|
26
|
+
time.sleep(1)
|
|
27
|
+
|
|
28
|
+
# Method 2: Using the action ID for insert track
|
|
29
|
+
print("\nMethod 2: Using action ID for insert track...")
|
|
30
|
+
client.send_message("/action", [40001]) # Action ID for "Insert new track"
|
|
31
|
+
time.sleep(1)
|
|
32
|
+
client.send_message("/track/1/name", ["Method 2 Track"])
|
|
33
|
+
time.sleep(1)
|
|
34
|
+
|
|
35
|
+
# Method 3: Using the track/add command with position
|
|
36
|
+
print("\nMethod 3: Using /track/add with position parameter...")
|
|
37
|
+
client.send_message("/track/add/last", None)
|
|
38
|
+
time.sleep(1)
|
|
39
|
+
client.send_message("/track/2/name", ["Method 3 Track"])
|
|
40
|
+
time.sleep(1)
|
|
41
|
+
|
|
42
|
+
# Method 4: Using a different command structure
|
|
43
|
+
print("\nMethod 4: Using /insert/track command...")
|
|
44
|
+
client.send_message("/insert/track", None)
|
|
45
|
+
time.sleep(1)
|
|
46
|
+
client.send_message("/track/3/name", ["Method 4 Track"])
|
|
47
|
+
time.sleep(1)
|
|
48
|
+
|
|
49
|
+
print("\nTest completed. Check REAPER to see which method worked for creating new tracks.")
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
main()
|