Skip to main content
Glama

REAPER MCP Server

by shiehn
reaper_mcp_development_guide.md5.66 kB
# Hybrid Lua–Python REAPER MCP Server **Detailed Development Guide** --- ## 0. Prerequisites | Requirement | Purpose | Extra Setup | |-------------|---------|-------------| | REAPER 6.83 or newer | Bundles embedded Lua 5.4 and full ReaScript API | None | | macOS 10.15 (Catalina) – 14.x | Supported by PyInstaller universal‑2 builds | None | | No external Python / Lua | The bridge runs on REAPER’s Lua; Python is bundled in your EXE | – | --- ## 1. Repository Layout ```text reaper-mcp/ ├─ lua/ │ └─ mcp_bridge.lua # 40‑line reflection stub ├─ server/ │ ├─ app.py # FastAPI entry‑point │ ├─ handles.py # ID↔pointer helpers │ ├─ client.py # Optional Python wrapper │ └─ pyproject.toml # Poetry / Hatch ├─ scripts/ │ └─ install.sh # One‑liner installer ├─ .github/workflows/ │ └─ build-mac.yml # CI: universal build + release └─ README.md ``` --- ## 2. Lua Reflection Stub (`lua/mcp_bridge.lua`) ```lua local json = require('dkjson') -- bundled local socket = require('socket').udp() socket:setpeername('127.0.0.1', 9000) local handles, next_id = {}, 1 local function pack(v) if type(v) == 'userdata' then local id = next_id; next_id = id + 1 handles[id] = v return { __ptr = id } end return v end function mcp_bridge(call, ...) local ok, ret = pcall(_G[call], ...) if ok then ret = pack(ret) end socket:send(json.encode{ ok = ok, ret = ret }) return ret end function mcp_lookup(id) return handles[id] end ``` *Runs on every REAPER install with zero extra dependencies.* --- ## 3. Python Server (`server/app.py`) ```python import json, socket from fastapi import FastAPI UDP = ('127.0.0.1', 9000) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) app = FastAPI() def call_lua(fname, args): sock.send(json.dumps({'call': fname, 'args': args}).encode()) data, _ = sock.recvfrom(65536) return json.loads(data) @app.post('/call') async def call(body: dict): return call_lua(body['call'], body.get('args', [])) def main(): import uvicorn uvicorn.run('server.app:app', port=8765, reload=False) ``` `pyproject.toml` (Poetry example): ```toml [project] name = "reaper_mcp_server" version = "0.1.0" dependencies = ["fastapi", "uvicorn[standard]"] [tool.poetry.scripts] mcp-server = "server.app:main" ``` --- ## 4. Local Development & Tests ```bash # launch REAPER manually and run mcp_bridge.lua poetry install poetry run mcp-server & curl -X POST http://127.0.0.1:8765/call -d '{"call":"InsertTrackAtIndex","args":[0,true]}' pytest ``` --- ## 5. Freeze to Universal macOS EXE ```bash # On Intel builder pyinstaller -F -n mcp_server_x86 server/app.py --target-arch x86_64 # On Apple‑Silicon builder pyinstaller -F -n mcp_server_arm server/app.py --target-arch arm64 # Merge lipo -create dist/mcp_server_x86 dist/mcp_server_arm -output dist/mcp_server_universal tar -czf mcp_server-mac.tar.gz -C dist mcp_server_universal ``` --- ## 6. GitHub Actions CI (`.github/workflows/build-mac.yml`) ```yaml name: build-mac on: [push, workflow_dispatch] jobs: build: strategy: matrix: arch: [x86_64, arm64] runs-on: macos-latest steps: - uses: actions/checkout@v4 - run: brew install python@3.11 pyinstaller - run: ./scripts/build_${{ matrix.arch }}.sh merge: needs: build runs-on: macos-latest steps: - uses: actions/download-artifact@v4 - run: lipo -create dist/*_x86 dist/*_arm -output mcp_server_universal - run: gh release upload ... ``` --- ## 7. One‑Liner Installer (`scripts/install.sh`) ```bash #!/usr/bin/env bash set -e SCRIPTS="$HOME/Library/Application Support/REAPER/Scripts" curl -fsSL https://raw.githubusercontent.com/your-org/reaper-mcp/main/lua/mcp_bridge.lua -o "$SCRIPTS/mcp_bridge.lua" xattr -rd com.apple.quarantine "$SCRIPTS/mcp_bridge.lua" APPDIR="$HOME/Applications/MCP-Server" mkdir -p "$APPDIR" LATEST=$(curl -s https://api.github.com/repos/your-org/reaper-mcp/releases/latest | grep mac | cut -d '"' -f4) curl -L "$LATEST" | tar -xz -C "$APPDIR" xattr -rd com.apple.quarantine "$APPDIR/mcp_server" open -a "$APPDIR/mcp_server" echo 'Open REAPER ➜ Actions ➜ Run "mcp_bridge.lua" (add to startup).' ``` --- ## 8. Optional Enhancements * **ReaPack feed** for auto‑updating the Lua stub. * **launchd plist** to auto‑start the server on login. * **Startup Action** so REAPER runs the stub automatically. --- ## 9. Common macOS Questions | Question | Answer | |----------|--------| | Do I need to enable Python in REAPER? | No—the Python process is external. | | Will Gatekeeper complain? | The installer clears the quarantine bit, so no warning dialog. | | Intel vs Apple Silicon? | Universal‑2 EXE runs natively on both CPUs. | --- ## 10. Claude Code Workflow ```bash claude-code py . # edit files, run pytest, build scripts ./scripts/build_arm.sh ``` Claude Code can modify any file in the repo; commit and push to trigger CI. --- ## 11. Milestone Checklist | Milestone | Deliverable | |-----------|-------------| | M0 | Lua stub responds with API version. | | M1 | `/call` inserts a track (CRUD proven). | | M2 | Universal PyInstaller build produced by CI. | | M3 | `install.sh` completes on fresh macOS VM in <30 s. | | M4 | ReaPack auto‑updates verified. | | M5 | launchd + Startup Action for hands‑free load. | --- *Project complete once M3 is reached—users get full‑CRUD MCP server with a single command.*

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shiehn/total-reaper-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server