Skip to main content
Glama

Waveform MCP

Ein MCP-Server, der einem LLM-Agenten die Kontrolle über Tracktion Waveform gibt. Bitten Sie Claude, einen Song zu schreiben, einen Mix auszubalancieren oder als MP3 zu rendern – und sehen Sie zu, wie Waveform es ausführt.

Synthwave-Arrangement, das vollständig über das MCP erstellt wurde Ein 64-Takt-Synthwave-Instrumental, komponiert über MCP-Tool-Aufrufe – Drums, Bass, zwei Pads, Counter, Arp, Lead. Sektionsmarker, Tempo-Automation, Sidechain-Pump, Plate-Reverb, Clip-Fades, vollständige Master-Kette.


Was Sie damit erhalten

  • 107 MCP-Tools für den Edit-Lebenszyklus, Spuren, MIDI, Audio-Clips, Plugins, Automation, Musiktheorie, Mix-Balance, Rendering, Loop-Bibliothek, VST-Erkennung, Schema-Erfassung und Waveform-UI-Steuerung

  • Zwei End-to-End-Komponistencompose_lofi_track und compose_synthwave_track – die vollständig arrangierte, gemischte und gerenderte Songs schreiben

  • Ein Ambient-Komponistcompose_rainstorm – für Regen-, Wind- und Donner-Klanglandschaften

  • Eine musiktheoretische Wissensebene – Tonleitern, Akkordfolgen, Kadenzen, Songformen, Stimmführungsregeln, Mix-Balance-Referenzpegel pro Genre

  • Verifizierter Round-Trip zwischen dem In-Memory-Modell und dem .tracktionedit-XML von Waveform

  • Clip-Level-Fades, Gain, Offset, Automationskurven – bewährte Primitive, die das LLM nutzen kann, um musikalisch zu iterieren

  • Zuverlässige Workflow-Schleifecompose → write → reload via File → Revert to saved → listen → tweak


Status

Funktioniert End-to-End unter Windows + Waveform 13. macOS/Linux-Pfade für die Inhaltsermittlung (Presets, Loop-Bibliothek, VST-Liste) sind vorhanden, die UI-Steuerung erfolgt derzeit jedoch nur unter Windows via UIA / pywinauto.

Entwickelt und getestet durch ca. 30 Stunden Mensch-in-der-Schleife-Iteration mit Claude. Beide Komponisten wurden mehrfach als MP3 gerendert und der Benutzer hat die resultierenden Tracks abgenommen.


Schnellstart

Installation

cd "C:\path\to\waveform MCP"
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -e .

Mit Claude verbinden (Code, Desktop oder ein beliebiger MCP-Client)

~/.claude.json oder die MCP-Konfiguration Ihres Clients:

{
  "mcpServers": {
    "waveform": {
      "command": "waveform-mcp"
    }
  }
}

Ausprobieren

Open Waveform, then ask Claude:

  "Use compose_synthwave_track to make a synthwave song,
   save it to my Documents/Waveform folder, and reload it
   in Waveform so I can hear it."

Das LLM ruft compose_synthwave_trackwaveform_revert_to_saved auf und Sie drücken auf Play. Dann iterieren Sie: "dreh den Bass leiser" → das LLM aktualisiert MIX_BALANCE["synthwave"]["bass"] und lädt neu.


Architektur

Vier Ebenen, jede mit einem klaren Vertrag:

┌──────────────────────────────────────────────────────────────┐
│  LLM (Claude / any MCP client)                               │
└────────────────────────────┬─────────────────────────────────┘
                             │ MCP stdio
┌────────────────────────────▼─────────────────────────────────┐
│  MCP server (server.py) — 107 tools                          │
└────────────────────────────┬─────────────────────────────────┘
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
      ┌──────────────┐ ┌──────────┐ ┌──────────────┐
      │ Edit model   │ │ Knowledge│ │  Waveform    │
      │ (in-memory)  │ │  (data)  │ │  UI control  │
      ├──────────────┤ ├──────────┤ ├──────────────┤
      │ Tracks       │ │ Scales   │ │ pywinauto +  │
      │ Clips        │ │ Chords   │ │ UIA + ffmpeg │
      │ Notes        │ │ Forms    │ │              │
      │ Plugins      │ │ Mix      │ │ Menu invoke  │
      │ Automation   │ │ Velocity │ │ Revert       │
      │ Markers      │ │ Rhythm   │ │ Render→MP3   │
      └──────┬───────┘ └──────────┘ └──────┬───────┘
             │                             │
             ▼                             ▼
   ┌──────────────────┐          ┌────────────────────┐
   │ xml_writer.py    │          │ Waveform 13        │
   │ xml_reader.py    │ ◀──────▶ │ (the running app)  │
   │ ↓ .tracktionedit │          └────────────────────┘
   └──────────────────┘

Wichtige Designentscheidung: Das Modell ist kein 1:1-Abbild des Tracktion ValueTree – es ist die Form, mit der das LLM arbeiten möchte, die beim Speichern auf das XML projiziert und beim Laden zurückprojiziert wird. Dies macht die Tools einfach (audio_clip_import(track_id, file_path, start_beats, length_beats, fade_in_beats, ...)) anstatt das LLM zu zwingen, in JUCE-Interna zu denken.


Tool-Katalog

Edit-Lebenszyklus (edit.py)

edit_create · edit_open · edit_save · flush · edit_summary · edit_inspect · undo · narrate

Spuren + Mix (tracks.py)

track_add · track_remove · mix_set · mix_apply_reference · send_add · marker_add · tempo_set · key_set

mix_apply_reference(track_id, genre, role) schlägt das dB-Ziel aus einer kuratierten Mix-Balance-Tabelle (MIX_BALANCE[genre][role]) nach – die Referenz "Kick ist der Anker, Bass 5-6 dB darunter", destilliert in einen aufrufbaren Befehl.

MIDI (midi.py)

midi_clip_add · midi_notes_add · midi_notes_clear · midi_clip_quantize

Audio-Clips (audio.py, clips.py)

audio_clip_import (mit gain_db, fade_in_beats, fade_out_beats, offset_in_source_beats) clip_list · clip_set · clip_move · clip_resize · clip_duplicate · clip_remove

Plugins (plugins.py, preset_library.py)

plugin_list · plugin_add · plugin_set_param · plugin_remove plugin_add_reverb (Plate / Natural / Non-linear mit sinnvollen Standardwerten) plugin_add_drum_kit (Sampler-basiert, ein SOUND pro Pad) plugin_add_modifier (LFO / Envelope / Sidechain – Schema TBD bei vollständiger Waveform-Unterstützung) plugin_discover (parst knownPluginList64.settings, um installierte VSTs aufzulisten) waveform_preset_list · waveform_preset_read · waveform_plugin_types

Automation (automation.py)

automation_add · automation_envelope · automation_clear · automation_list

Ziele: pan und plugin/<plugin_id>/<param>. Das Lautstärke-Ziel ist auf API-Ebene deaktiviert – das Lautstärke-Plugin von Waveform respektiert unser <AUTOMATIONCURVE>-Schema nicht und schaltet die Spur stumm. Verwenden Sie mix_set/mix_apply_reference für statische Pegel und clip_set(fade_in_beats|fade_out_beats) für Fades. (Das MCP verweigert target="volume" mit einer klaren Fehlermeldung, die auf Alternativen hinweist.)

Musiktheoretisches Wissen (music_theory.py, music_theory_data.py)

17 Abfragetools: theory_scale · theory_modes · theory_diatonic_chords · theory_chord_progression · theory_cadences · theory_song_form · theory_section · theory_genre · theory_arrangement_layers · theory_velocity · theory_rhythm · theory_voice_leading_rules · theory_heuristics · theory_surprise_devices · theory_borrowed_chords · theory_mix_balance · theory_search

Die Daten dahinter:

  • 13 Tonleitern (Dur-Modi, harmonisch Moll, Pentatonik, Blues, etc.)

  • 25+ Akkordfolgen (axis_pop, ii_V_I, andalusian, lament_bass, …)

  • Kadenzen, Songformen, Sektionen mit Rollen-/Dichte-/Dynamikprofilen

  • 14 Genres mit typischem BPM, Tonart-Tendenzen, Instrumenten, charakteristischen Folgen

  • Velocity- / Rhythmus-Maps (Swing-Verhältnisse, Akzent-Bumps, Ghost-Note-Bereiche)

  • 13 Songwriting-Heuristiken (Dreierregel, Kontrast erforderlich, Überraschungsquote, …)

  • 7 Überraschungseffekte (Truck-Driver-Modulation, Trugschluss, …)

  • Mix-Balance-Referenztabelle – 7 Genres × 14 Rollen, vollständig annotiert

Komponisten (composer.py)

  • compose_lofi_track – 32-Takt-Lofi mit Drums, Bass, Keys, Pad, Melodie, Counter; sektionsbewusste Velocity-Envelopes; Tempo-Automation; Lofi-Master-Kette

  • compose_synthwave_track – 64-Takt-Synthwave mit 7 Spuren; 9-Sektions-Form (Intro/Verse/Chorus/Verse/Chorus/Bridge/Buildup/ChorusFinal/Outro); Bass-Feel pro Sektion (Half-time / 8th-pump / Walking); sektionsbezogene Arp-Themen; Sidechain-Filter-Pump; Sektionsmarker; Clip-Fades

  • compose_rainstorm – Ambient-Klanglandschaft mit Regen + Wind + tiefpassgefiltertem, entferntem Donner; Gain-Randomisierung pro Clip; Offset-Trim; Track-FX

Rendern (render.py, waveform_workflows.py)

waveform_render_export · waveform_render_to_mp3 (verwendet gebündeltes ffmpeg + libmp3lame)

Waveform UI-Steuerung (waveform_workflows.py)

waveform_new_project · waveform_save · waveform_revert_to_saved (der Freischalter für die Iterationsschleife) · waveform_close_active_tab · waveform_active_tab · waveform_project_loaded · waveform_menu_invoke · waveform_add_track · waveform_select_track · waveform_insert_clip_on_track · waveform_build_skeleton

App-Lebenszyklus (waveform_app.py)

waveform_locate · waveform_status · waveform_launch · waveform_focus · waveform_quit · waveform_settings_dir

Loop-Bibliothek (loops.py)

loop_search (nach Tempo / Takten / Name) · loop_drop (automatische Länge, Anpassung an Tempo)

Schema-Erfassung (schema_capture.py)

schema_snapshot_current_edit · schema_diff_snapshots · schema_list_snapshots

Low-Level UI / Desktop (win_input.py, desktop.py)

18 Primitive für Fensterverwaltung, UIA-Inspektion, Senden von Tasten/Klicks, Screenshots.


Layout

waveform-mcp/
├── src/waveform_mcp/
│   ├── server.py                  MCP server entry (stdio)
│   ├── model.py                   Edit / Track / Clip / Note / AutomationLane dataclasses
│   ├── xml_writer.py              Edit → .tracktionedit
│   ├── xml_reader.py              .tracktionedit → Edit
│   ├── audio_convert.py           ffmpeg-backed MP3→WAV cache for Sampler sources
│   ├── music_theory_data.py       SCALES, PROGRESSIONS, GENRES, MIX_BALANCE, ...
│   ├── events.py                  event bus + JSONL log
│   ├── diff.py                    Edit-diff for change events
│   ├── tools/
│   │   ├── edit.py                Edit lifecycle
│   │   ├── tracks.py              Tracks + mix balance
│   │   ├── midi.py                MIDI clips/notes
│   │   ├── audio.py               Audio clip import
│   │   ├── clips.py               Clip mutators (move, resize, duplicate, set)
│   │   ├── plugins.py             Plugin add + reverb / drum kit / modifier helpers
│   │   ├── automation.py          Automation lanes (pan + plugin params)
│   │   ├── preset_library.py      Factory preset browser
│   │   ├── loops.py               Loop library search + drop
│   │   ├── render.py              Render stubs
│   │   ├── waveform_app.py        App lifecycle
│   │   ├── waveform_workflows.py  UI workflows (revert, render-to-mp3, etc.)
│   │   ├── desktop.py             Generic desktop primitives
│   │   ├── win_input.py           Windows UIA + keystroke primitives
│   │   ├── schema_capture.py      Hand-fixture capture for schema reverse-engineering
│   │   ├── music_theory.py        Theory query tools
│   │   ├── composer.py            compose_lofi_track, compose_synthwave_track, compose_rainstorm
│   │   └── common.py              @op decorator (apply + diff + event)
│   └── preview/
│       ├── app.py                 FastAPI + websocket
│       └── static/                HTML / JS piano-roll
├── tests/
├── docs/
│   ├── img/synthwave_arrangement.png
│   ├── ARCHITECTURE.md
│   ├── EVENT_SCHEMA.md
│   └── EDIT_MODEL.md
├── pyproject.toml
└── README.md

Die Iterationsschleife, die tatsächlich funktioniert

Nach vielen Fehlstarts ist hier die Schleife, die es dem LLM und dem Benutzer ermöglicht, an einem Track zusammenzuarbeiten, ohne Waveform in jedem Zyklus neu zu starten:

1. Compose / mutate            → composer.compose_*  or clip_set / mix_apply_reference
2. Save to disk                → edit_save / flush  (writes .tracktionedit)
3. Reload in Waveform          → waveform_revert_to_saved
                                  (File → Revert to saved state, auto-confirms popup)
4. User listens                → "turn the arp up"
5. Update MIX_BALANCE or run a clip mutator
6. → goto 2

Der entscheidende Schritt war die Entdeckung des Menüpunkts Datei → Auf gespeicherten Zustand zurücksetzen in Waveform: Er zwingt den geöffneten Edit dazu, neu von der Festplatte zu laden, was externe Änderungen sichtbar macht, ohne das Projekt schließen/öffnen zu müssen. waveform_revert_to_saved automatisiert diesen Pfad mit Wiederholungsversuchen.


Mix-Balance-Referenz

mix_apply_reference liest aus einer kuratierten Tabelle: "Kick ist der Anker; Bass 5-6 dB darunter; Lead ähnlich wie Bass; Pad/Arp 6-9 dB unter Lead; Ambience am leisesten" – destilliert aus Genre-Tutorials, Mastering-Blogs und durch Gehör abgestimmten Iterationen:

MIX_BALANCE["synthwave"] = {
    "drums": -7, "kick": -6, "snare": -10, "hat": -16,
    "bass": -25, "sub_bass": -28,           # background-level texture
    "lead": -15, "pad": -19, "arp": -8,     # arp-driven mix
    "counter": -14, ...
}

Komponisten rufen tracks.mix_apply_reference({track_id, genre, role}) einmal pro Spur auf. Passen Sie die Tabelle einmal an, und jeder Komponist gleicht neu aus.

Quellen für die Tabelle:


Bekannte Einschränkungen

  • Spur-Lautstärke AUTOMATIONCURVE ist deaktiviert. Das volume-Plugin von Waveform respektiert unser Kurvenschema nicht und schaltet die betroffene Spur stumm. Das MCP verweigert das Ziel mit einer klaren Fehlermeldung und verweist auf funktionierende Alternativen (Clip-Fades, mehrere Clips mit Gain pro Clip, statisches mix_set).

  • Plugin-Modifier-Matrix ist experimentell. plugin_add_modifier schreibt eine generische Modmatrix-Form; benötigt ein manuell bearbeitetes Fixture, um das Schema pro Plugin zu bestätigen, bevor LFO-Modulation für 4OSC und ähnliche zuverlässig funktioniert.

  • Headless-Rendering noch nicht implementiert. waveform_render_to_mp3 steuert den UI-Export von Waveform – funktioniert, erfordert aber, dass Waveform läuft. Ein C++-Helfer, der tracktion_engine verlinkt, ist die endgültige Lösung.

  • Linux/macOS UI-Steuerung fehlt. Inhaltsermittlung (Presets, Loop-Bibliothek, VST-Liste) ist OS-bewusst; UI-Automatisierung ist nur unter Windows verfügbar.


Bausteine für nächste Iterationen

  • Erfassung eines echten Waveform-Fixtures für <AUTOMATIONCURVE paramID="volume">, damit Lautstärke-Automation wieder aktiviert werden kann

  • C++ Headless-Render-Helfer für tracktion_engine

  • Drum Sampler / Micro Drum Sampler echtes Fixture (derzeit Rückgriff auf einfachen Sampler)

  • Sidechain-Modifier-Erfassung

  • Unterstützung für Clip Launcher (v13)

  • Linux UI-Steuerung via xdotool/wmctrl, sobald UIA nicht mehr der einzige Pfad ist


Lizenz

GPL-3.0-or-later (entspricht tracktion_engine, falls/wenn der C++-Render-Helfer damit verlinkt wird).

A
license - permissive license
-
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

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/jarmstrong158/waveform-MCP'

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