MCP (Model Context Protocol) server for controlling Audacity through mod-script-pipe. Designed for hands-off LLM-driven audio pipelines — Claude Code (or any MCP client) can generate, process, and export audio entirely through tool calls with no manual Audacity interaction required.
- Connects to Audacity via
mod-script-pipe - Thread-safe — all pipe I/O is serialized through a lock and run off the event loop via
asyncio.to_thread, so rapid sequential tool calls never interleave - Generator tools work on empty projects — if no tracks exist the server writes a silent WAV to
/tmp, imports it, and uses it as the generation target (Audacity'sDurationscripting parameter is silently ignored; a selection is required) - Full parameterized tools for
Export2,Import2,Select,GetInfo,SetTrackStatus,SetTrackAudio,OpenProject2,SaveProject2 - Compound
generate_and_exporttool that handles an entire generate → select → export → cleanup cycle in one call - Auto-detects pipe path suffix in
/tmp(e.g..501) - Uses
stdiotransport (compatible with Claude Code, Claude Desktop, Codex)
- Audacity 3.x+
- Python 3.10+
mod-script-pipeenabled in Audacity (see below)
git clone https://github.com/DaRealDaHoodie/mcp-audacity.git
cd mcp-audacity
./scripts/setup.shManual setup:
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install "mcp[cli]>=1.6.0" "httpx>=0.28.1"- Open Audacity.
- Go to Modules preferences:
- macOS:
Audacity → Settings → Modules - Windows/Linux:
Edit → Preferences → Modules
- macOS:
- Set
mod-script-pipefromNeworDisabledtoEnabled. - Restart Audacity.
Verify the pipes exist:
ls -l /tmp/audacity_script_pipe.to.* /tmp/audacity_script_pipe.from.*If both files appear, Audacity is ready.
# Audacity must already be running with mod-script-pipe enabled
./scripts/smoke_test.sh./scripts/run.shExpected startup log:
Audacity MCP server starting up
Opened Audacity mod-script-pipe
Connected to Audacity mod-script-pipe
Add to your MCP config (e.g. ~/.claude/claude_desktop_config.json or via claude mcp add):
{
"mcpServers": {
"audacity": {
"command": "/absolute/path/to/mcp-audacity/.venv/bin/python",
"args": ["/absolute/path/to/mcp-audacity/audacity_mcp_server.py"]
}
}
}codex mcp add AudacityMCP -- /absolute/path/to/mcp-audacity/.venv/bin/python /absolute/path/to/mcp-audacity/audacity_mcp_server.pyAll generators work on empty projects. If no tracks exist, the server automatically creates a silent track of the correct duration in /tmp, imports it, and runs the generator against it (the generator replaces the silence). If tracks already exist, the generator applies to the current selection as usual.
Why the workaround? Audacity's scripting API silently ignores the
Durationparameter — generators always require an existing track with a selection. The server handles this transparently so you never have to think about it.
| Tool | Key parameters | Notes |
|---|---|---|
cmd_Noise |
duration, noise_type (White/Pink/Brownian), amplitude |
|
cmd_Tone |
duration, frequency, amplitude, waveform (Sine/Square/Sawtooth) |
|
cmd_Chirp |
duration, start_frequency, end_frequency, start_amplitude, end_amplitude, waveform, interpolation |
Frequency sweep |
cmd_Pluck |
duration, pitch (MIDI note number), fade (Abrupt/Gradual) |
|
cmd_DtmfTones |
sequence, duration, amplitude |
Phone keypad tones |
cmd_RhythmTrack |
tempo, beats_per_bar, duration |
Click track |
cmd_RissetDrum |
duration, frequency, decay, cf, bw, noise, gain |
|
cmd_Nyquist |
command |
Full Nyquist/Lisp DSP expression run against the selection, e.g. (scale 0.5 s) |
All effects below are fully parameterized and apply without opening any dialog.
| Tool | Key parameters | Notes |
|---|---|---|
cmd_Amplify |
ratio, allow_clipping |
ratio=0.5 → -6 dB, ratio=2.0 → +6 dB |
cmd_LoudnessNormalization |
normalize_to (LUFS/RMS), lufs_level, rms_level, dual_mono |
-23.0 LUFS = broadcast, -14.0 LUFS = streaming |
cmd_Normalize |
peak_level (dBFS), apply_volume, remove_dc_offset, stereo_independent |
Peak normalization — different from LUFS loudness |
cmd_Compressor |
threshold, noise_floor, ratio, attack_time, release_time, normalize, use_peak |
Uses Audacity's LegacyCompressor internally |
cmd_Limiter |
threshold_db, makeup_target_db, knee_width_db, lookahead_ms, release_ms |
Hard ceiling; use after compression |
cmd_Reverb |
room_size, reverberance, hf_damping, wet_gain, dry_gain, stereo_width, wet_only |
All values 0–100 except gains (dB) |
cmd_Echo |
delay (seconds), decay (0.0–1.0) |
Simple echo/repeat effect |
cmd_Repeat |
count |
Repeats selection; total plays = count + 1 |
cmd_ChangePitch |
percentage, use_high_quality |
Percentage shift e.g. 50.0 ≈ one octave up |
cmd_ChangeSpeed |
percent |
Changes speed and pitch together |
cmd_ChangeTempo |
percent, use_high_quality |
Changes tempo without affecting pitch |
cmd_TruncateSilence |
threshold (dBFS), action, minimum, truncate, compress |
action: "Truncate Detected Silence" or "Compress Excess Silence" |
cmd_Paulstretch |
stretch_factor, time_resolution |
Extreme time-stretch; stretch_factor=10.0 = 10× longer |
cmd_BassAndTreble |
bass (dB), treble (dB), gain (dB), link_sliders |
EQ adjustment, ±30 dB range |
cmd_ClickRemoval |
threshold (0–900), max_spike_width (0–40 samples) |
Removes clicks and pops |
cmd_NoiseReduction |
(no parameters) | Applies using last captured profile — see note below |
cmd_NoiseGate |
threshold, mode, stereo_link, level_reduction, attack, hold, decay |
Gate or analyze mode |
cmd_HighPassFilter |
frequency (Hz), rolloff (dB6–dB48) |
Cuts below frequency |
cmd_LowPassFilter |
frequency (Hz), rolloff (dB6–dB48) |
Cuts above frequency |
cmd_NotchFilter |
frequency (Hz), q |
Removes a specific frequency; higher Q = narrower notch |
cmd_AdjustableFade |
fade_type (Up/Down/SCurveUp/SCurveDown), curve, units, gain0, gain1 |
More control than plain FadeIn/FadeOut |
cmd_Tremolo |
wave, phase, wet, lfo |
Amplitude modulation; lfo in Hz |
cmd_StereoToMono |
(no parameters) | Mix stereo track down to mono |
Remaining effects with no meaningful automation parameters (FadeIn, FadeOut, Reverse, Invert, Repair, etc.) are available as no-parameter tools — they apply with Audacity's defaults.
Audacity's scripting API exposes no parameters for NoiseReduction. The two-pass profile capture cannot be automated. Workflow:
- In Audacity, select a region containing only background noise
Effects → Noise Reduction → Get Noise Profile- Select the audio you want to clean
- Call
cmd_NoiseReduction— it applies the last captured profile
For fully automated noise cleanup, use cmd_NoiseGate instead (fully parameterized, no manual step).
| Tool | Key parameters | Notes |
|---|---|---|
cmd_ApplyMacro |
name |
Runs a saved Audacity macro by exact name. Use Macro Manager in Audacity to create macros that chain any sequence of effects. |
Macros are the most powerful tool for complex repeatable pipelines — build a chain once in Audacity, then fire it from Claude with a single cmd_ApplyMacro call.
| Tool | Key parameters | Notes |
|---|---|---|
cmd_Import2 |
filename (absolute path) |
Import audio as new track |
cmd_Export2 |
filename, num_channels |
Format inferred from extension: .wav .ogg .mp3 .flac .aiff |
cmd_OpenProject2 |
filename, add_to_history |
Open .aup3 project |
cmd_SaveProject2 |
filename, add_to_history |
Save .aup3 project |
| Tool | Key parameters | Notes |
|---|---|---|
cmd_Select |
start, end (seconds), track (0-based), track_count, mode (Set/Add/Remove) |
Combined time + track selection |
cmd_SelectTime |
start, end, relative_to |
Time-only selection; relative_to: ProjectStart/ProjectEnd/SelectionStart/etc. |
cmd_SelectTracks |
track (0-based), track_count, mode |
Track-only selection |
cmd_GetInfo |
info_type (Tracks/Clips/Labels/Envelopes/Boxes/Commands/Preferences/Selection), format |
Inspect project state. Use Type=Selection to read current selection. |
cmd_SetTrackStatus |
track (0-based), name, selected |
Rename or select/deselect a track |
cmd_SetTrackAudio |
track (0-based), mute, solo, volume (dB), pan (-1..1) |
Set mix properties |
cmd_SetLabel |
label (0-based index), text, start, end |
Edit an existing label's text or time range |
cmd_SetClip |
track, at (current start), color (Color0–Color3), start (new start) |
Move or recolor a clip |
cmd_SetEnvelope |
track, time, value (0.0–2.0), delete |
Add, move, or remove a volume envelope point |
cmd_BeatFinder |
threshold (0–100) |
Detect beats and add labels |
cmd_LabelSounds |
threshold, measurement, silence_duration, sound_duration, label_type, text |
Auto-label by sound/silence detection |
cmd_StereoToMono |
(no parameters) | Convert stereo to mono |
| Tool | Key parameters | Notes |
|---|---|---|
cmd_GetPreference |
name (key path) |
Read any Audacity preference, e.g. Quality/DefaultProjectSampleRate |
cmd_SetPreference |
name, value, reload |
Write any Audacity preference. reload=True applies immediately. |
Common preference keys for pipelines:
| Key | What it controls |
|---|---|
Quality/DefaultProjectSampleRate |
Default sample rate for new projects (e.g. "44100", "48000") |
Quality/DefaultProjectSampleFormat |
Bit depth: "float", "int24", "int16" |
AudioIO/PlaybackDevice |
Playback device name |
Handles an entire generate-and-export cycle in one call. Useful for batch pipelines where you want to produce many audio files without orchestrating individual steps.
generator: Noise | Tone | Chirp | Pluck
duration: seconds (float)
output_path: absolute path including filename and extension
format is inferred from extension: .wav .ogg .flac .aiff
amplitude: 0.0–1.0
frequency: Hz (for Tone/Chirp/Pluck)
noise_type: White | Pink | Brownian (Noise only)
waveform: Sine | Square | Sawtooth (Tone/Chirp only)
num_channels: 1 (mono) or 2 (stereo)
Internally it runs: generate → SelectAll → Export2 → TrackClose. Because exactly one track is created per call, a single TrackClose: leaves the project empty and ready for the next iteration without opening a new Audacity window on each call.
Example prompt to Claude:
"Generate 5 WAV files: white noise 2s, 440Hz sine 1s, 880Hz sawtooth 1s, pink noise 3s, and a plucked A4 1s. Save them to ~/sounds/ as noise_white.wav, tone_440.wav, tone_880_saw.wav, noise_pink.wav, pluck_a4.wav."
Claude Code
│
▼ MCP tool calls (stdio)
audacity_mcp_server.py
│
▼ named pipe (mod-script-pipe)
Audacity 3.x
│
▼ file output
/your/output/directory/
One pipe, one process. Audacity's mod-script-pipe creates a single pair of FIFOs. The MCP server opens them and holds them for its lifetime. No other process should open the same pipes while the server is running — if a standalone script also tries to read pipe_from, responses will be split between the two readers and both will get corrupted output. All Audacity interaction should go through this server.
Commands are sequential. The threading lock means every tool call waits for BatchCommand finished before the next command is sent. This is safe for rapid sequential calls but means there is no parallelism on the Audacity side by design.
Audacity must be running. The server does not launch Audacity. Start Audacity with mod-script-pipe enabled before starting the server.
For pure audio synthesis and format conversion, Python's wave module + ffmpeg is simpler and has no pipe constraints. Use this server when you need Audacity specifically:
| Need | Use |
|---|---|
| Synthesize tones, noise, sweeps | Either — Audacity via this server or Python + ffmpeg |
| Batch OGG/MP3 export + loudness normalization | ffmpeg (loudnorm filter) is easier |
| Noise reduction, click/crackle removal | Audacity — stronger algorithms |
| Nyquist scripting | Audacity only |
Load an existing .aup3 project and process it |
Audacity only |
| LLM-driven batch generation of many files | cmd_generate_and_export compound tool, or Python + ffmpeg |
| Symptom | Fix |
|---|---|
Failed to open Audacity pipes |
Confirm Audacity is running with mod-script-pipe enabled; check /tmp/audacity_script_pipe.* exists |
spawn uv ENOENT |
Use absolute paths in MCP config |
"Noise" requires one or more tracks to be selected |
This should not occur with the MCP tools — they auto-bootstrap a silent track on empty projects. If you see this, confirm you are calling cmd_Noise (not the raw Noise: bare command) and that the server was restarted after the latest changes. |
ApplyMacro does nothing or errors |
The macro name must match exactly as shown in Audacity's Macro Manager (case-sensitive). Verify the macro exists before calling cmd_ApplyMacro. |
| Nyquist command errors | Expressions must be valid Nyquist/Lisp. The s variable refers to the current selection. Test in Audacity's Nyquist Prompt first. |
| Commands time out or return empty | Another process is reading pipe_from. Stop it and restart the MCP server. |
| Tools behave inconsistently across calls | Ensure you are on the latest version; it serializes all commands through a lock and reads until BatchCommand finished |
MIT