normalize_project
Measure a project's integrated loudness and automatically adjust the master volume to hit a specified LUFS target, such as -14 for streaming or -16 for podcasts.
Instructions
Measure the project's integrated loudness, then adjust the master volume so the output hits the target LUFS level. Common targets: -14 LUFS (streaming), -16 LUFS (podcasts), -23 LUFS (broadcast).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| target_lufs | No |
Implementation Reference
- The normalize_project tool handler: renders project to temp WAV, measures LUFS via pyloudnorm, computes gain adjustment, and sets master volume to hit target LUFS.
@mcp.tool() def normalize_project(target_lufs: float = -14.0) -> dict: """ Measure the project's integrated loudness, then adjust the master volume so the output hits the target LUFS level. Common targets: -14 LUFS (streaming), -16 LUFS (podcasts), -23 LUFS (broadcast). """ try: import soundfile as sf import pyloudnorm as pyln from reaper_mcp.render_tools import render_to_temp_file tmp = render_to_temp_file() try: data, rate = sf.read(tmp) meter = pyln.Meter(rate) current_lufs = meter.integrated_loudness(data) finally: if os.path.exists(tmp): os.unlink(tmp) if current_lufs == float("-inf"): return {"success": False, "error": "Project appears to be silent"} gain_db = target_lufs - current_lufs project = get_project() master = project.master_track new_vol_db = master.volume + gain_db master.volume = new_vol_db return { "success": True, "original_lufs": round(current_lufs, 1), "target_lufs": target_lufs, "gain_applied_db": round(gain_db, 1), "new_master_volume_db": round(new_vol_db, 1), } except Exception as e: return {"success": False, "error": str(e)} - src/reaper_mcp/mastering_tools.py:18-18 (registration)The register_tools function in mastering_tools.py, which is called from server.py to register the normalize_project tool via @mcp.tool() decorator.
def register_tools(mcp): - src/reaper_mcp/server.py:17-28 (registration)Import and invocation of mastering_tools.register_tools in server.py, which registers normalize_project as an MCP tool.
from reaper_mcp.mastering_tools import register_tools as _reg_mastering from reaper_mcp.analysis_tools import register_tools as _reg_analysis _reg_project(mcp) _reg_track(mcp) _reg_midi(mcp) _reg_fx(mcp) _reg_audio(mcp) _reg_mixing(mcp) _reg_render(mcp) _reg_mastering(mcp) _reg_analysis(mcp) - src/reaper_mcp/render_tools.py:47-56 (helper)render_to_temp_file helper: renders the current project to a temporary WAV file for loudness analysis by normalize_project.
def render_to_temp_file(sample_rate: int = 48000) -> str: """ Render the current project to a temporary WAV file and return its path. Used by analysis and mastering tools. Caller is responsible for deleting the file. """ import tempfile tmp = tempfile.mktemp(suffix=".wav") _set_render_settings(tmp, "wav", sample_rate, 24, 2, bounds=0) RPR.Main_OnCommand(41824, 0) return tmp - src/reaper_mcp/connection.py:27-29 (helper)get_project helper used by normalize_project to obtain the REAPER project reference for adjusting master volume.
def get_project() -> reapy.Project: ensure_connected() return reapy.Project()