Skip to main content
Glama

DJ-MCP: AI-Controlled Professional Music Production & DJ Workstation

Python Version MCP Server

DJ-MCP is an installable, cross-platform Python library and Model Context Protocol (MCP) server engineered for autonomous AI-controlled music production, DJ mixing, audio editing, and mastering.

The AI agent acts as the producer and DJ. The library acts as the deterministic professional audio engine, executing sample-accurate audio manipulation, musical analysis, and DSP without synthetic hallucinations or destructive modifications to source files.


Table of Contents


Related MCP server: Ableton Live MCP Ultra v2

1. Architectural Overview

DJ-MCP decouples high-level creative decision-making from low-level signal processing:

┌─────────────────────────────────────────────────────────────┐
│             LLM / Agent (LM Studio, Claude, Codex)           │
└──────────────────────────────┬──────────────────────────────┘
                               │ MCP Protocol (stdio / sse)
┌──────────────────────────────▼──────────────────────────────┐
│                      DJ-MCP Server Layer                    │
│   - Strict Pydantic Schemas   - Structured Error Responses  │
│   - Actionable Next Steps     - Sequential Workflows        │
├─────────────────────────────────────────────────────────────┤
│                      Session & Project                      │
│   - Non-Destructive Timeline  - Decks & Crossfader State    │
│   - Mixer Channels & Sends    - Snapshot / Rollback Journal │
├──────────────────────────────┬──────────────────────────────┤
│               Core Audio & Analysis Engines                 │
│   ┌──────────────────────────┼──────────────────────────┐   │
│   │   Spotify Pedalboard     │         Librosa          │   │
│   │   (JUCE C++ Native DSP)  │  (BPM, Key, Transients)  │   │
│   ├──────────────────────────┼──────────────────────────┤   │
│   │      PyLoudnorm          │      Meta AI Demucs      │   │
│   │  (ITU-R BS.1770-4 LUFS)  │ (Neural Stem Separation) │   │
│   ├──────────────────────────┼──────────────────────────┤   │
│   │   Rubber Band / Soxr     │     FFmpeg & Soundfile   │   │
│   │ (Time-Stretch & Pitch)   │   (Lossless Audio I/O)   │   │
│   └──────────────────────────┴──────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Key Principles

  1. Deterministic Processing: Identical parameters always yield identical PCM sample output.

  2. Non-Destructive by Default: Original source files are never overwritten unless explicitly instructed with a destructive flag. Edits are stored as timeline offset slices.

  3. Sample Accuracy: Beat positioning, cue slicing, and clip alignment preserve exact sample boundaries.

  4. Actionable Errors for Small LLMs: Failed or precondition-blocked operations return structured error envelopes containing the exact next tool and parameters required to fix the issue.


2. System Requirements & Platform Support

DJ-MCP runs natively across:

  • Linux: x86_64 and ARM64 (Debian/Ubuntu, Fedora, Arch, RHEL)

  • macOS: Apple Silicon (M1/M2/M3/M4) and Intel x86_64 (macOS 12.0+)

  • Windows: x64 and ARM64 (Windows 10, Windows 11)

External Tools

  • FFmpeg / FFprobe: Required for audio transcoding, metadata probing, and container export (MP3, AAC, OGG).

  • Python: 3.10, 3.11, 3.12, or 3.13.


3. Installation

Clone and install in editable mode (automatically installs all audio engines, PyLoudnorm, Demucs, Pedalboard, Librosa, and PyTorch):

git clone https://github.com/antigravity-audio/dj-mcp.git
cd dj-mcp
pip install -e .

Pre-download AI Separation Models

The Meta Demucs neural network will pre-download during installation. To manually verify or pre-cache weights anytime:

dj-mcp download-models

4. Diagnostic System Doctor

Run the built-in system doctor to audit hardware capabilities, GPU acceleration, audio libraries, and file permissions:

dj-mcp doctor

Example output:

============================================================
DJ-MCP SYSTEM DOCTOR DIAGNOSTIC REPORT
============================================================
Overall Status   : HEALTHY
Operating System : Linux (x86_64)
Python Version   : 3.13.12
CPU Cores        : 12
RAM Total/Avail  : 15.28 GB / 11.1 GB
GPU Available    : True (cuda)
------------------------------------------------------------
ENGINES & DSP:
  [✓ INSTALLED ] ffmpeg         : Audio container decoding, encoding, format conversion
  [✓ INSTALLED ] soundfile      : Sample-accurate uncompressed PCM and lossless I/O
  [✓ INSTALLED ] pedalboard     : Native C++ JUCE DSP effects (EQ, filters, compressor, limiter, reverb, delay)
  [✓ INSTALLED ] librosa        : BPM, beat-grid, onset/transient, chroma and key detection
  [✓ INSTALLED ] pyloudnorm     : ITU-R BS.1770-4 / EBU R128 integrated and momentary LUFS loudness analysis
  [✓ INSTALLED ] demucs         : High-fidelity neural source separation (vocals, drums, bass, other)
  [✓ INSTALLED ] rubberband     : High-quality time-stretching and pitch shifting
------------------------------------------------------------
CODECS & FORMATS:
  [✓ SUPPORTED   ] WAV
  [✓ SUPPORTED   ] FLAC
  [✓ SUPPORTED   ] AIFF
  [✓ SUPPORTED   ] OGG
  [✓ SUPPORTED   ] MP3
  [✓ SUPPORTED   ] AAC
------------------------------------------------------------
Disk Free Space  : 94441 MB
Cache Directory  : /home/igris/dj-mcp/.dj_cache (Writable: True)
Temp Directory   : /home/igris/dj-mcp/.dj_temp (Writable: True)
============================================================

To obtain output as structured JSON for automation:

dj-mcp doctor --json

5. MCP Server Setup & Client Configuration

Start the server using standard I/O transport (default for MCP agents):

dj-mcp.server

Or via the main CLI:

dj-mcp server --transport stdio

For HTTP Server-Sent Events (SSE) remote transport:

dj-mcp server --transport sse --host 0.0.0.0 --port 8080

Client Configuration

LM Studio

In Settings -> MCP Servers, add:

{
  "mcpServers": {
    "dj-mcp": {
      "command": "dj-mcp.server",
      "args": ["--transport", "stdio"]
    }
  }
}

Claude Desktop

Add to your claude_desktop_config.json:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "dj-mcp": {
      "command": "dj-mcp.server",
      "args": ["--transport", "stdio"]
    }
  }
}

Gemini CLI / OpenAI Codex

Configure in your respective CLI settings or environment profile:

{
  "servers": {
    "dj-mcp": {
      "command": "dj-mcp.server"
    }
  }
}

Cursor / Windsurf

In Settings -> Features -> MCP, click Add New MCP Server:

  • Name: dj-mcp

  • Type: command

  • Command: dj-mcp.server


6. Complete Tutorials

Tutorial 1: Python Library Quickstart

This script imports an audio file, analyzes its musical properties, sets up a timeline track, applies parametric EQ and compression, masters to streaming loudness, and renders to FLAC:

from pathlib import Path
from ai_dj import (
    Session,
    AudioClip,
    Track,
    MasteringProcessor,
    get_default_config,
)
from ai_dj.export import export_audio_to_file

# 1. Initialize session and project
config = get_default_config()
session = Session(config)
project = session.create_project(project_id="quickstart", name="Quickstart Project", sample_rate=44100)

# 2. Import and analyze audio
track_file = Path("samples/drop.wav")
lib_track = session.library.import_track(track_file, track_id="drop")
analysis = session.library.analyze_track("drop")

print(f"BPM: {analysis['bpm']}, Key: {analysis['key']} ({analysis['camelot']})")
print(f"Loudness: {analysis['loudness']['integrated_lufs']} LUFS")

# 3. Create a timeline track and non-destructive clip
track = Track(track_id="t_lead", name="Lead Track", channel_id="ch_lead")
clip = AudioClip(
    clip_id="c_lead_1",
    name="Lead Drop",
    source_file=track_file,
    source_offset_sec=0.0,
    timeline_position_sec=0.0,
    duration_sec=16.0,
    gain_db=-1.5,
    fade_in_sec=0.05,
    fade_out_sec=0.5,
)
track.add_clip(clip)
project.timeline.add_track(track)

# 4. Render unmastered timeline mix
raw_mix = session.renderer.render_timeline(
    project.timeline,
    project.mixer,
    start_sec=0.0,
    end_sec=16.0,
)

# 5. Master to Spotify/Apple Music streaming standards (-14 LUFS, -1.0 dBTP ceiling)
masterer = MasteringProcessor(profile="streaming", target_lufs=-14.0, true_peak_ceiling_db=-1.0)
mastered_audio, stats = masterer.process_audio(raw_mix, sample_rate=44100)

print(f"Mastered Loudness: {stats['final_lufs']} LUFS, Peak: {stats['final_peak_dbfs']} dBFS")

# 6. Export lossless FLAC
out_path = Path("exports/mastered_drop.flac")
export_audio_to_file(mastered_audio, out_path, sample_rate=44100, bit_depth=24, audio_format="flac")
print(f"Exported to: {out_path}")

Tutorial 2: Automated 2-Deck Beatmatched Transition

In this tutorial, an AI agent loads two tracks onto Deck A and Deck B, matches their tempos, establishes a 4-beat loop, and performs an equal-power crossfader transition.

from ai_dj import get_active_session
from ai_dj.mcp.tools import (
    tool_project_create,
    tool_library_import,
    tool_track_analyze,
    tool_create_beatgrid,
    tool_deck_load,
    tool_deck_play,
    tool_deck_sync,
    tool_loop_create,
    tool_mixer_crossfade,
    tool_render_project,
)

# 1. Create project
tool_project_create(project_id="dj_mix", name="Club Set", sample_rate=44100, num_decks=2)

# 2. Import tracks
tool_library_import(file_path="music/house_a.wav", track_id="track_a")
tool_library_import(file_path="music/house_b.wav", track_id="track_b")

# 3. Analyze BPM and generate beatgrids
res_a = tool_track_analyze(track_id="track_a")["result"]
res_b = tool_track_analyze(track_id="track_b")["result"]

tool_create_beatgrid(track_id="track_a", bpm=res_a["bpm"], first_beat_sec=res_a["first_beat_sec"])
tool_create_beatgrid(track_id="track_b", bpm=res_b["bpm"], first_beat_sec=res_b["first_beat_sec"])

# 4. Load Deck A and Deck B
tool_deck_load(deck_id="deck_a", track_id="track_a")
tool_deck_load(deck_id="deck_b", track_id="track_b")

# 5. Sync Deck B to Deck A's tempo and phase
tool_deck_sync(deck_id="deck_b", master_deck_id="deck_a")

# 6. Establish a 4-beat transition loop on Deck A
tool_loop_create(deck_id="deck_a", length_beats=4.0, start_sec=16.0)

# 7. Start playback and crossfade from Deck A to Deck B
tool_deck_play(deck_id="deck_a")
tool_deck_play(deck_id="deck_b")

# Move crossfader from Left (-1.0) to Center (0.0) to Right (+1.0)
tool_mixer_crossfade(position=0.0, curve="equal_power")
tool_mixer_crossfade(position=1.0, curve="smooth")

Tutorial 3: Non-Destructive Timeline Arrangement

Edit and arrange audio without altering the underlying raw files:

from ai_dj.mcp.tools import (
    tool_clip_create,
    tool_clip_split,
    tool_clip_move,
    tool_clip_time_stretch,
    tool_clip_pitch,
    tool_clip_fade,
)

# 1. Place a 30-second source segment onto timeline at 0.0s
tool_clip_create(
    track_id="t_vocal",
    clip_id="vocal_hook",
    source_file="vocals.wav",
    timeline_position_sec=0.0,
    source_offset_sec=10.0,
    duration_sec=8.0,
)

# 2. Split into two 4-second clips
tool_clip_split(
    track_id="t_vocal",
    clip_id="vocal_hook",
    split_offset_sec=4.0,
    new_clip_id="vocal_hook_pt2",
)

# 3. Time stretch second half by 1.25x and shift pitch up +2 semitones
tool_clip_time_stretch(track_id="t_vocal", clip_id="vocal_hook_pt2", rate=1.25)
tool_clip_pitch(track_id="t_vocal", clip_id="vocal_hook_pt2", semitones=2.0)

# 4. Apply a 50ms fade-in to eliminate clicks
tool_clip_fade(track_id="t_vocal", clip_id="vocal_hook_pt2", fade_in_sec=0.05, fade_out_sec=0.2)

Tutorial 4: Neural Stem Separation & Remixing

Isolate vocals, drums, bass, and instrumental elements using Meta's Demucs backend:

from ai_dj.mcp.tools import (
    tool_separate_stems,
    tool_job_status,
    tool_stem_mute,
    tool_stem_solo,
    tool_stem_gain,
    tool_stem_export,
)

# 1. Launch stem separation as a background job
job_resp = tool_separate_stems(audio_path="song.wav", output_dir="stems/song_stems", model_name="htdemucs")
job_id = job_resp["job_id"]
print(f"Background Job ID: {job_id}")

# 2. Check job progress
status = tool_job_status(job_id=job_id)
print(f"Status: {status['result']['status']}, Progress: {status['result']['progress']}%")

# 3. Once complete, adjust individual stem levels (e.g. acapella extract)
tool_stem_mute(set_id="song_stems", stem_name="drums", mute=True)
tool_stem_mute(set_id="song_stems", stem_name="bass", mute=True)
tool_stem_mute(set_id="song_stems", stem_name="other", mute=True)
tool_stem_solo(set_id="song_stems", stem_name="vocals", solo=True)
tool_stem_gain(set_id="song_stems", stem_name="vocals", gain_db=2.5)

# 4. Recombine and export the isolated vocal track
tool_stem_export(set_id="song_stems", output_path="exports/isolated_vocals.wav")

Tutorial 5: Mastering for Streaming & Club Systems

Enforce target loudness and peak ceilings with multi-band mastering:

from ai_dj.mcp.tools import (
    tool_master_process,
    tool_master_validate,
)

# Option A: Streaming Profile (-14.0 LUFS, -1.0 dBTP ceiling)
stream_res = tool_master_process(
    input_file="mixdown.wav",
    output_file="masters/streaming_master.wav",
    profile="streaming",
)
print("Streaming Master Stats:", stream_res["result"]["stats"])

# Validate against standard
val_stream = tool_master_validate(file_path="masters/streaming_master.wav", target_profile="streaming")
assert val_stream["result"]["is_compliant"] is True

# Option B: High-Energy Club/DJ Master (-9.0 LUFS, -0.3 dBTP ceiling)
club_res = tool_master_process(
    input_file="mixdown.wav",
    output_file="masters/club_master.wav",
    profile="dj_master",
    true_peak_ceiling_db=-0.3,
)
print("Club Master Stats:", club_res["result"]["stats"])

7. Complete MCP Tool Catalog & Schemas

DJ-MCP exposes high-level, deterministic tools with strict Pydantic parameter schemas.

1. Capabilities & Environment

Tool

Description

Key Arguments

system_capabilities

Comprehensive OS, CPU, RAM, GPU, audio backends, and codecs report.

None

available_engines

Status of FFmpeg, Soundfile, Pedalboard, Librosa, PyLoudnorm, Demucs.

None

available_codecs

Supported container formats (WAV, FLAC, AIFF, OGG, MP3, AAC).

None

audio_devices

Active sound card playback and recording devices.

None

available_models

Installed neural separation weights (htdemucs, etc.).

None

available_plugins

List of native DSP filters, dynamics, and spatial effects.

None

workspace_get

Get active workspace directory path, free disk space, and defaults.

None

workspace_set

Dynamically change active workspace directory for all future exports.

directory: str

2. Project Lifecycle

Tool

Description

Key Arguments

project_create

Initialize a new session project.

project_id: str, name: str, sample_rate: int=44100, num_decks: int=2

project_open

Load .djproj state file from disk.

file_path: str

project_save

Atomically serialize project state.

file_path: Optional[str]

project_close

Close active project session.

None

project_info

Get tracks, timeline duration, and deck states.

None

project_validate

Check for broken file paths, clipping, or missing routing.

None

project_snapshot

Take an undo/recovery snapshot.

label: Optional[str]

project_restore

Restore project to snapshot ID.

snapshot_id: str

project_undo

Undo previous action.

None

project_redo

Redo previously undone action.

None

3. Audio Library & Scanning

Tool

Description

Key Arguments

library_scan

Scan directory for audio files.

directory: str, recursive: bool=True

library_search

Query library by title, artist, BPM range, key.

query: str, min_bpm: float, max_bpm: float, key: str

library_import

Register file in session library.

file_path: str, track_id: Optional[str]

library_remove

Deregister track from library.

track_id: str

library_metadata

Inspect ID3/container tags and sample specs.

track_id: str

4. DJ Decks & Synchronization

Tool

Description

Key Arguments

deck_create

Add an extra DJ deck (deck_c, deck_d).

deck_id: str

deck_load

Load an analyzed track onto a deck.

deck_id: str, track_id: str

deck_unload

Eject track from deck.

deck_id: str

deck_play

Start deck playback.

deck_id: str

deck_pause

Pause deck playback.

deck_id: str

deck_stop

Stop playback and reset playhead to 0.0s.

deck_id: str

deck_seek

Jump to position in seconds (quantized).

deck_id: str, position_sec: float, quantize: bool=True

deck_sync

Lock tempo and beat-phase to master deck with smart half/double-time support.

deck_id: str, master_deck_id: str, allow_half_double_time: bool=True

deck_set_bpm

Set explicit playback tempo.

deck_id: str, bpm: float

deck_set_pitch

Adjust pitch fader percentage.

deck_id: str, pitch_percent: float

deck_set_key

Shift pitch in semitones (Key Lock active).

deck_id: str, semitones: float

5. Beat Grid & Musical Analysis

Tool

Description

Key Arguments

detect_bpm

Auto-detect tempo and beat timestamps.

file_path: str

detect_beats

Extract onset beat times.

file_path: str

detect_downbeats

Identify bar markers (1.1, 2.1, etc.).

file_path: str

create_beatgrid

Anchor beatgrid to first downbeat.

track_id: str, bpm: float, first_beat_sec: float=0.0

correct_beatgrid

Nudge grid offset (+/-) or adjust BPM.

track_id: str, offset_sec: float, bpm_override: float

quantize_to_grid

Round time to nearest quantum (bar, beat, 1/2, 1/4, 1/8, 1/16).

track_id: str, position_sec: float, quantum: str='beat'

analyze_key

Detect musical scale and Camelot wheel code.

file_path: str

analyze_loudness

Measure integrated LUFS, peak, true-peak, and RMS.

file_path: str

analyze_phase

Check stereo phase correlation [-1.0, 1.0].

file_path: str

analyze_clipping

Count digital overs and clipped samples.

file_path: str

6. Non-Destructive Editing

Tool

Description

Key Arguments

clip_create

Place audio segment on timeline.

track_id: str, clip_id: str, source_file: str, timeline_position_sec: float, duration_sec: float

clip_trim

Non-destructively trim clip start/end.

track_id: str, clip_id: str, start_delta_sec: float, end_delta_sec: float

clip_split

Split clip into two at offset.

track_id: str, clip_id: str, split_offset_sec: float, new_clip_id: str

clip_cut

Delete clip from track.

track_id: str, clip_id: str

clip_join

Merge two contiguous clips into one.

track_id: str, clip_a_id: str, clip_b_id: str, new_clip_id: str

clip_move

Reposition clip on timeline.

track_id: str, clip_id: str, new_timeline_position_sec: float

clip_duplicate

Duplicate clip with timeline offset.

track_id: str, clip_id: str, new_clip_id: str, offset_sec: Optional[float]

clip_fade

Apply fade-in / fade-out curves.

track_id: str, clip_id: str, fade_in_sec: float, fade_out_sec: float

clip_gain

Adjust clip gain in dB.

track_id: str, clip_id: str, gain_db: float

clip_reverse

Reverse audio playback in clip.

track_id: str, clip_id: str, reverse: bool=True

clip_pitch

Pitch shift audio in semitones.

track_id: str, clip_id: str, semitones: float

clip_time_stretch

Time-stretch playback rate (e.g. 1.25x).

track_id: str, clip_id: str, rate: float

clip_normalize

Normalize peak amplitude to target dBFS.

track_id: str, clip_id: str, target_peak_dbfs: float=-0.5

7. Mixer, Routing & Effects

Tool

Description

Key Arguments

mixer_create_channel

Add mixer channel strip.

channel_id: str, name: Optional[str]

mixer_set_gain

Set fader volume in dB [-60.0, 24.0].

channel_id: str, gain_db: float

mixer_set_pan

Constant-power pan [-1.0, 1.0].

channel_id: str, pan: float

mixer_mute

Mute/unmute channel.

channel_id: str, mute: bool

mixer_solo

Solo channel strip.

channel_id: str, solo: bool

mixer_crossfade

Crossfader position [-1.0, 1.0] and curve.

position: float, curve: str='equal_power'

mixer_route

Assign channel to crossfader (a, b, thru).

channel_id: str, crossfader_assign: str

effect_add

Insert DSP effect plugin.

channel_id: str, effect_id: str, effect_type: str, parameters: dict

effect_set_parameter

Modify active effect parameter.

channel_id: str, effect_id: str, parameter_name: str, value: Any

8. Mastering & Rendering

Tool

Description

Key Arguments

master_process

Apply full mastering chain to file.

input_file: str, output_file: str, profile: str='dj_master', target_lufs: float, true_peak_ceiling_db: float

master_validate

Audit compliance against target standard.

file_path: str, target_profile: str='streaming'

render_project

Render entire timeline mix to audio file (MP3 default, WAV, FLAC).

output_path: str, start_sec: float=0.0, end_sec: Optional[float], format: str='mp3', bit_rate_kbps: int=320

render_preview

Render short preview snippet (15s).

output_path: str, start_sec: float=0.0, duration_sec: float=15.0, format: str='mp3'

export_audio

Transcode file to target codec & bit depth.

input_file: str, output_file: str, format: str='mp3', bit_depth: int=24, bit_rate_kbps: int=320

audio_convert_format

Convert single file or batch directory to MP3, FLAC, WAV, OGG, AAC, OPUS, AIFF with storage savings analysis.

input_file: Union[str, List[str]], output_file: Optional[str], target_format: str='mp3', bit_rate_kbps: int=320

9. Direct Audio & Pitch/Tempo Editing (Audacity-Style Standalone DSP)

Tool

Description

Key Arguments

audio_reverb

Apply lush reverb with custom room size, damping, and mix to a single song, multiple songs, or an entire folder.

input_files: Union[str, List[str]], output_dir: Optional[str], room_size: float=0.5, wet_level: float=0.33, dry_level: float=0.67

audio_apply_effect

Apply any Pedalboard effect (reverb, delay, eq, compressor, limiter, chorus, distortion, filter) to single or batch files.

input_files: Union[str, List[str]], effect_type: str='reverb', parameters: Dict[str, Any], output_dir: Optional[str]

audio_change_tempo

Change tempo of audio file(s) or track(s) by target BPM, percentage, or duration with pitch preservation. Supports single file, list, or folder.

input_file: Union[str, List[str]], output_file: Optional[str], output_dir: Optional[str], target_bpm: float, preserve_pitch: bool=True

audio_change_pitch

Shift pitch of audio file(s) or track(s) by semitones, cents, or target musical key (e.g. G minor to A minor). Supports single file, list, or folder.

input_file: Union[str, List[str]], output_file: Optional[str], output_dir: Optional[str], semitones: float, from_key: str, to_key: str

audio_change_speed

Varispeed pitch+speed change (analog tape, vinyl 33.3 to 45 RPM).

input_file: str, output_file: str, speed_ratio: float, from_rpm: float, to_rpm: float

audio_paulstretch

Extreme phase-randomized spectral stretch (3x - 50x) for ambient drone design.

input_file: str, output_file: str, stretch_factor: float=8.0, window_size_sec: float=0.25

audio_reverse

Play audio file backward in time.

input_file: str, output_file: str

audio_invert_polarity

Invert signal phase/polarity (both channels, left, or right).

input_file: str, output_file: str, channels: str='both'

audio_truncate_silence

Automatically strip or compress silent intervals below threshold dB.

input_file: str, output_file: str, threshold_db: float=-50.0, min_silence_sec: float=0.5, truncate_to_sec: float=0.0

audio_denoise

Adaptive noise reduction and downward noise gating.

input_file: str, output_file: str, reduction_db: float=12.0

audio_declick

Detect and interpolate clicks, pops, and vinyl crackle.

input_file: str, output_file: str, sensitivity: float=0.5

audio_vocal_remover

Center-channel extraction / cancellation with bass preservation (karaoke / vocal isolation).

input_file: str, output_file: str, mode: str='remove_vocals', low_cutoff_hz: float=120.0

audio_merge

Mix/merge multiple audio files or stems together with anti-clipping normalization.

input_files: Union[List[str], str], output_file: str, normalize: bool=False

stems_merge

Automatically scan a stems directory and recombine all stems into a single song file.

stems_dir: str, output_file: str, normalize: bool=True, target_peak_dbfs: float=-0.5

timeline_set_tempo

Set master DAW project/timeline BPM with optional non-destructive clip re-timing.

bpm: float, stretch_clips: bool=True

timeline_get_tempo

Get active project/timeline BPM and time signature.

(none)


8. Error Handling & Recovery for Small LLMs

Small language models frequently fail when tools return plain text error strings like "invalid argument".

DJ-MCP enforces Structured Error Envelopes:

{
  "success": false,
  "error": {
    "code": "DECK_NOT_FOUND",
    "message": "Deck 'deck_c' does not exist in current session.",
    "reason": "resource_not_found",
    "required_action": "deck_create",
    "suggested_tool": "deck_create",
    "suggested_arguments": {
      "deck_id": "deck_c"
    },
    "recoverable": true
  },
  "next_actions": [
    {
      "action": "deck_create",
      "tool": "deck_create",
      "arguments": {
        "deck_id": "deck_c"
      }
    }
  ]
}

Self-Correction Loop

When a model encounters a failure:

  1. It reads error.suggested_tool and error.suggested_arguments.

  2. It executes the suggested tool to satisfy the precondition.

  3. It retries the original operation with guaranteed state validity.


9. Sequential Workflows & Conditional Execution

The workflow engine allows complex multi-step pipelines with automated rollback:

from ai_dj.mcp.tools import (
    tool_workflow_create,
    tool_workflow_add_step,
    tool_workflow_execute,
)

# 1. Create a sequential workflow
tool_workflow_create(workflow_id="prep_track", name="Track Import & Prep Pipeline")

# Step 1: Import Track
tool_workflow_add_step(
    workflow_id="prep_track",
    tool_name="library_import",
    arguments={"file_path": "audio/track.wav", "track_id": "my_song"},
    on_failure="stop",
)

# Step 2: Analyze BPM and Key
tool_workflow_add_step(
    workflow_id="prep_track",
    tool_name="track_analyze",
    arguments={"track_id": "my_song"},
    on_failure="rollback",
)

# Step 3: Load into Deck A only if analysis succeeds
tool_workflow_add_step(
    workflow_id="prep_track",
    tool_name="deck_load",
    arguments={"deck_id": "deck_a", "track_id": "my_song"},
    condition_field="bpm",
    condition_operator="is_not_none",
    on_failure="stop",
)

# 2. Execute the entire pipeline atomically
result = tool_workflow_execute(workflow_id="prep_track")
print("Workflow Result:", result)

10. Performance, Resource Management & Caching

  • Vectorized C++ DSP: Filter calculations and dynamics run in compiled C++ through Spotify's pedalboard (JUCE framework) with SIMD optimizations.

  • Analysis Caching: Audio hash + parameter hashes are stored under .dj_cache/analysis_<hash>.json. Identical audio files are analyzed in < 1ms.

  • Atomic Disk Writes: Every save and render operation uses temporary swap files (.tmp.<pid>) with POSIX fsync replacement, ensuring project files never corrupt during abrupt stops.

  • Auto-Cleanup: Temporary render buffers are automatically tracked and collected at process exit (atexit).


11. Testing & Verification

The codebase includes integration and unit tests covering DSP accuracy, deck synchronization, beatgrid generation, timeline editing, mastering compliance, and MCP tool invocations.

Execute the test suite:

pytest -v tests

Output:

============================= test session starts ==============================
platform linux -- Python 3.13.12, pytest-9.1.1, pluggy-1.6.0
rootdir: /home/igris/dj-mcp
collected 24 items

tests/test_analysis_and_beatgrid.py::test_key_detection_and_camelot_compatibility PASSED [  4%]
tests/test_analysis_and_beatgrid.py::test_beatgrid_quantization PASSED   [  8%]
tests/test_analysis_and_beatgrid.py::test_audio_analysis_on_fixture PASSED [ 12%]
tests/test_capabilities.py::test_system_capabilities_structure PASSED    [ 16%]
tests/test_capabilities.py::test_doctor_execution PASSED                 [ 20%]
tests/test_decks_and_dj.py::test_deck_lifecycle PASSED                   [ 25%]
tests/test_decks_and_dj.py::test_deck_sync_and_pitch PASSED              [ 29%]
tests/test_decks_and_dj.py::test_cues_and_loops PASSED                   [ 33%]
tests/test_decks_and_dj.py::test_crossfader_curves PASSED                [ 37%]
tests/test_dsp_and_audio.py::test_stereo_panning PASSED                  [ 41%]
tests/test_dsp_and_audio.py::test_stereo_width_and_correlation PASSED    [ 45%]
tests/test_dsp_and_audio.py::test_dc_offset_removal PASSED               [ 50%]
tests/test_dsp_and_audio.py::test_pedalboard_effect_chain PASSED         [ 54%]
tests/test_dsp_and_audio.py::test_rubberband_pitch_and_time_stretch PASSED [ 58%]
tests/test_editing_and_timeline.py::test_clip_trim_and_split PASSED      [ 62%]
tests/test_editing_and_timeline.py::test_track_and_timeline_rendering PASSED [ 66%]
tests/test_errors_and_recovery.py::test_structured_error_dict PASSED     [ 70%]
tests/test_errors_and_recovery.py::test_atomic_write PASSED              [ 75%]
tests/test_errors_and_recovery.py::test_undo_redo_stack PASSED           [ 79%]
tests/test_jobs_and_workflows.py::test_job_manager_execution PASSED      [ 83%]
tests/test_jobs_and_workflows.py::test_sequential_workflow_execution PASSED [ 87%]
tests/test_mastering_and_rendering.py::test_mastering_processor PASSED   [ 91%]
tests/test_mastering_and_rendering.py::test_project_rendering_and_export PASSED [ 95%]
tests/test_mcp_tools.py::test_end_to_end_mcp_tool_workflow PASSED        [100%]

======================== 24 passed in 7.71s ========================

12. License & Attribution

This library is released under the MPL-2.0 License. See LICENSE for full details.

Third-Party Dependencies

  • Pedalboard: Spotify (GPL v3 / JUCE)

  • SoundFile: Erik de Castro Lopo / Bastian Bechtold (BSD 3-Clause)

  • Librosa: Brian McFee et al. (ISC License)

  • PyLoudnorm: Christian Steinmetz (MIT License)

  • Demucs: Meta AI (MIT License)

  • FastMCP: Model Context Protocol Team (MIT License)

Related MCP Connectors

Related MCP Servers