@mthines/reaper-mcp 0.6.0-beta.3.2 → 0.6.0

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.
package/README.md CHANGED
@@ -272,15 +272,65 @@ Processing decisions adapt to the genre:
272
272
  | Orchestral | -23 to -16 | Preserve dynamics, hall reverb staging |
273
273
  | Metal | -11 to -8 | V-scoop guitars, tight drums, 4-guitar wall |
274
274
 
275
+ ## Autonomous Mode (Allow All Tools)
276
+
277
+ By default Claude Code asks permission for each MCP tool call. To let the mix agents work autonomously, add the REAPER tools to your allow list.
278
+
279
+ Add to your project's `.claude/settings.json` (or `~/.claude/settings.json` for global):
280
+
281
+ ```json
282
+ {
283
+ "permissions": {
284
+ "allow": [
285
+ "mcp__reaper__get_project_info",
286
+ "mcp__reaper__list_tracks",
287
+ "mcp__reaper__get_track_properties",
288
+ "mcp__reaper__set_track_property",
289
+ "mcp__reaper__add_fx",
290
+ "mcp__reaper__remove_fx",
291
+ "mcp__reaper__get_fx_parameters",
292
+ "mcp__reaper__set_fx_parameter",
293
+ "mcp__reaper__list_available_fx",
294
+ "mcp__reaper__search_fx",
295
+ "mcp__reaper__get_fx_preset_list",
296
+ "mcp__reaper__set_fx_preset",
297
+ "mcp__reaper__play",
298
+ "mcp__reaper__stop",
299
+ "mcp__reaper__record",
300
+ "mcp__reaper__get_transport_state",
301
+ "mcp__reaper__set_cursor_position",
302
+ "mcp__reaper__read_track_meters",
303
+ "mcp__reaper__read_track_spectrum",
304
+ "mcp__reaper__read_track_lufs",
305
+ "mcp__reaper__read_track_correlation",
306
+ "mcp__reaper__read_track_crest",
307
+ "mcp__reaper__snapshot_save",
308
+ "mcp__reaper__snapshot_restore",
309
+ "mcp__reaper__snapshot_list",
310
+ "mcp__reaper__get_track_routing"
311
+ ]
312
+ }
313
+ }
314
+ ```
315
+
316
+ The format is `mcp__reaper__{tool_name}`. Once added, Claude Code will run these tools without prompting.
317
+
275
318
  ## CLI Commands
276
319
 
277
320
  ```bash
278
- reaper-mcp # Start MCP server (default)
279
- reaper-mcp serve # Start MCP server (stdio mode)
280
- reaper-mcp setup # Install Lua bridge + JSFX into REAPER
281
- reaper-mcp install-skills # Install AI knowledge into your project
282
- reaper-mcp doctor # Verify everything is configured
283
- reaper-mcp status # Check bridge connection
321
+ npx @mthines/reaper-mcp # Start MCP server (default)
322
+ npx @mthines/reaper-mcp serve # Start MCP server (stdio mode)
323
+ npx @mthines/reaper-mcp setup # Install Lua bridge + JSFX into REAPER
324
+ npx @mthines/reaper-mcp install-skills # Install AI knowledge + agents into your project
325
+ npx @mthines/reaper-mcp doctor # Verify everything is configured
326
+ npx @mthines/reaper-mcp status # Check bridge connection
327
+ ```
328
+
329
+ Or install globally for shorter commands:
330
+
331
+ ```bash
332
+ npm install -g @mthines/reaper-mcp
333
+ reaper-mcp setup
284
334
  ```
285
335
 
286
336
  ## Claude Code Integration
package/main.js CHANGED
@@ -963,7 +963,7 @@ import { fileURLToPath } from "node:url";
963
963
  import { homedir as homedir2 } from "node:os";
964
964
 
965
965
  // apps/reaper-mcp-server/src/cli.ts
966
- import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from "node:fs";
966
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
967
967
  import { join as join2 } from "node:path";
968
968
  function resolveAssetDir(baseDir, name) {
969
969
  const sibling = join2(baseDir, name);
@@ -1013,6 +1013,86 @@ var REAPER_ASSETS = [
1013
1013
  "mcp_correlation_meter.jsfx",
1014
1014
  "mcp_crest_factor.jsfx"
1015
1015
  ];
1016
+ var MCP_TOOL_NAMES = [
1017
+ // project
1018
+ "get_project_info",
1019
+ // tracks
1020
+ "list_tracks",
1021
+ "get_track_properties",
1022
+ "set_track_property",
1023
+ // fx
1024
+ "add_fx",
1025
+ "remove_fx",
1026
+ "get_fx_parameters",
1027
+ "set_fx_parameter",
1028
+ // discovery
1029
+ "list_available_fx",
1030
+ "search_fx",
1031
+ // presets
1032
+ "get_fx_preset_list",
1033
+ "set_fx_preset",
1034
+ // transport
1035
+ "play",
1036
+ "stop",
1037
+ "record",
1038
+ "get_transport_state",
1039
+ "set_cursor_position",
1040
+ // meters
1041
+ "read_track_meters",
1042
+ "read_track_spectrum",
1043
+ // analysis
1044
+ "read_track_lufs",
1045
+ "read_track_correlation",
1046
+ "read_track_crest",
1047
+ // snapshots
1048
+ "snapshot_save",
1049
+ "snapshot_restore",
1050
+ "snapshot_list",
1051
+ // routing
1052
+ "get_track_routing",
1053
+ // midi
1054
+ "create_midi_item",
1055
+ "list_midi_items",
1056
+ "get_midi_notes",
1057
+ "insert_midi_note",
1058
+ "insert_midi_notes",
1059
+ "edit_midi_note",
1060
+ "delete_midi_note",
1061
+ "get_midi_cc",
1062
+ "insert_midi_cc",
1063
+ "delete_midi_cc",
1064
+ "get_midi_item_properties",
1065
+ "set_midi_item_properties",
1066
+ // media
1067
+ "list_media_items",
1068
+ "get_media_item_properties",
1069
+ "set_media_item_properties",
1070
+ "split_media_item",
1071
+ "delete_media_item",
1072
+ "move_media_item",
1073
+ "trim_media_item",
1074
+ "add_stretch_marker",
1075
+ "get_stretch_markers",
1076
+ "delete_stretch_marker"
1077
+ ];
1078
+ function ensureClaudeSettings(settingsPath) {
1079
+ const allowList = MCP_TOOL_NAMES.map((t) => `mcp__reaper__${t}`);
1080
+ if (!existsSync(settingsPath)) {
1081
+ mkdirSync(join2(settingsPath, ".."), { recursive: true });
1082
+ const config = { permissions: { allow: allowList } };
1083
+ writeFileSync(settingsPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1084
+ return "created";
1085
+ }
1086
+ const existing = JSON.parse(readFileSync(settingsPath, "utf-8"));
1087
+ const existingAllow = existing?.permissions?.allow ?? [];
1088
+ const existingSet = new Set(existingAllow);
1089
+ const newTools = allowList.filter((t) => !existingSet.has(t));
1090
+ if (newTools.length === 0) return "unchanged";
1091
+ if (!existing.permissions) existing.permissions = {};
1092
+ existing.permissions.allow = [...existingAllow, ...newTools];
1093
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
1094
+ return "updated";
1095
+ }
1016
1096
 
1017
1097
  // apps/reaper-mcp-server/src/main.ts
1018
1098
  var __dirname = dirname(fileURLToPath(import.meta.url));
@@ -1094,6 +1174,22 @@ async function installSkills() {
1094
1174
  const count = copyDirSync(agentsSrc, globalAgentsDir);
1095
1175
  console.log(`Installed Claude agents (global): ${count} files \u2192 ${globalAgentsDir}`);
1096
1176
  }
1177
+ const localSettingsPath = join3(targetDir, ".claude", "settings.json");
1178
+ const localResult = ensureClaudeSettings(localSettingsPath);
1179
+ if (localResult === "created") {
1180
+ console.log(`Created Claude settings: ${localSettingsPath}`);
1181
+ } else if (localResult === "updated") {
1182
+ console.log(`Updated Claude settings with new REAPER tools: ${localSettingsPath}`);
1183
+ } else {
1184
+ console.log(`Claude settings already has all REAPER tools: ${localSettingsPath}`);
1185
+ }
1186
+ const globalSettingsPath = join3(globalClaudeDir, "settings.json");
1187
+ const globalResult = ensureClaudeSettings(globalSettingsPath);
1188
+ if (globalResult === "created") {
1189
+ console.log(`Created Claude settings (global): ${globalSettingsPath}`);
1190
+ } else if (globalResult === "updated") {
1191
+ console.log(`Updated Claude settings (global) with new REAPER tools: ${globalSettingsPath}`);
1192
+ }
1097
1193
  const mcpJsonPath = join3(targetDir, ".mcp.json");
1098
1194
  if (createMcpJson(mcpJsonPath)) {
1099
1195
  console.log(`
@@ -1103,7 +1199,8 @@ Created: ${mcpJsonPath}`);
1103
1199
  .mcp.json already exists \u2014 add the reaper server config manually if needed.`);
1104
1200
  }
1105
1201
  console.log("\nDone! Claude Code now has mix engineer agents, knowledge, and REAPER MCP tools.");
1106
- console.log('Try: @mix-engineer "Please gain stage my tracks"');
1202
+ console.log("All 48 REAPER tools are pre-approved \u2014 agents work autonomously.");
1203
+ console.log('\nTry: @mix-engineer "Please gain stage my tracks"');
1107
1204
  console.log('Or: @mix-analyzer "Roast my mix"');
1108
1205
  }
1109
1206
  async function doctor() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mthines/reaper-mcp",
3
- "version": "0.6.0-beta.3.2",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "MCP server for controlling REAPER DAW — real-time mixing, FX control, and frequency analysis for AI agents",
6
6
  "license": "MIT",
@@ -1116,12 +1116,12 @@ function handlers.create_midi_item(params)
1116
1116
  local track = reaper.GetTrack(0, track_idx)
1117
1117
  if not track then return nil, "Track " .. track_idx .. " not found" end
1118
1118
 
1119
- local item = reaper.CreateNewMIDIItemInProj(track, start_pos, end_pos)
1120
- if not item then return nil, "Failed to create MIDI item" end
1121
-
1122
1119
  reaper.Undo_BeginBlock()
1120
+ local item = reaper.CreateNewMIDIItemInProj(track, start_pos, end_pos)
1123
1121
  reaper.Undo_EndBlock("MCP: Create MIDI item", -1)
1124
1122
 
1123
+ if not item then return nil, "Failed to create MIDI item" end
1124
+
1125
1125
  -- Find the index of the new item on the track
1126
1126
  local item_count = reaper.CountTrackMediaItems(track)
1127
1127
  local new_idx = -1