openDAW MCP
# opendaw-mcp
<!-- REPO-METRICS: tools=557 skills=12 dsp=134 examples=226 -->
[](https://github.com/ameobius-ai/opendaw-mcp/actions/workflows/ci.yml)
[](TOOL_CATALOG.md)
[](skills/)
[](scripts/)
[](examples/)
MCP server for agent-native control of [openDAW](https://github.com/andremichelle/openDAW) — a browser-based digital audio workstation. Exposes 550+ tools (tracks, notes, effects, mixing, rendering) over the Model Context Protocol for AI agents (Claude, GPT, etc.).
```
AI agent ── MCP (stdio/SSE) ──▶ Python server ── Playwright ──▶ headless Chromium ──▶ openDAW
```
The server drives a real openDAW instance in headless Chromium via `page.evaluate()`. All project state lives in the browser's V8 context. Chromium starts lazily on the first tool call.
## Quick start
Requirements: Python 3.10+, Node.js 20+ (only to build the openDAW host once), Chromium via Playwright.
```bash
pip install -r requirements.txt
playwright install chromium
# Build the openDAW headless host once — it is a separate, small Vite app
# (NOT the openDAW monorepo, which has no headless-daw directory):
git clone --depth 1 https://github.com/andremichelle/openDAW-headless ../headless-daw
cd ../headless-daw
# its vite.config.ts readFileSync()s these certs at config load, even for `vite build`
openssl req -x509 -newkey rsa:2048 -keyout localhost-key.pem -out localhost.pem -days 365 -nodes -subj "/CN=localhost"
npm install && npm run build
cd ..
# Serve the built host statically on http://localhost:5174 (no Node needed at runtime):
OPENDAW_STATIC_DIR=../headless-daw/dist python scripts/serve_static.py &
python server.py # stdio transport
```
Client config example:
```json
{
"mcpServers": {
"opendaw": {
"command": "python",
"args": ["server.py"],
"env": {
"OPENDAW_URL": "http://localhost:5174",
"OPENDAW_MCP_MODE": "lite"
}
}
}
}
```
## Lite mode — recommended for weak machines
Full mode registers 557 tools; every tool schema costs tokens on each agent turn. Lite mode registers a curated set of 39 essential tools — about 92% less schema payload and a faster startup:
> **Note:** Lite mode is now the default. You only need to set `OPENDAW_MCP_MODE=full` if you want all tools.
```bash
OPENDAW_MCP_MODE=lite python server.py
```
Lite covers: project state, tracks, instruments, notes, regions, effects, mixing, BPM, markers, scriptable devices, render/export, and core composition helpers (drum pattern, bassline, melody, chord progression, mix preset).
## Low-memory tuning
Chromium is launched with low-RAM flags by default: `--disable-dev-shm-usage` (safe on Docker's 64 MB `/dev/shm`), `--disable-gpu`, `--mute-audio`, a V8 heap cap, and no background networking. Offline rendering is unaffected.
In Docker, `OPENDAW_SERVE_MODE=static` (the default in the image) replaces the Vite dev server with a zero-dependency Python static server (`scripts/serve_static.py`, ~10 MB RAM instead of ~300–500 MB for Node + Vite). The image builds the headless host at build time, so no Node.js is needed at runtime.
| Variable | Default | Description |
|---|---|---|
| `OPENDAW_V8_HEAP_MB` | `512` | V8 heap cap for the DAW page (`--max-old-space-size`) |
| `OPENDAW_CHROMIUM_ARGS` | — | Extra Chromium args, space-separated |
| `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` | — | Use system Chromium instead of the bundled one |
## Environment variables
> **Note:** As of this update, `OPENDAW_MCP_MODE=lite` is now the default mode for better token efficiency. Use `OPENDAW_MCP_MODE=full` to enable all 500+ tools.
| Variable | Default | Description |
|---|---|---|
| `OPENDAW_URL` | `http://localhost:5174` | URL of the served openDAW host |
| `OPENDAW_HOST_DIR` | `../headless-daw` | Path to headless DAW host directory |
| `OPENDAW_EXPORT_DIR` | `../exports` | Rendered audio output directory |
| `OPENDAW_MCP_MODE` | `lite` | `lite` = 39 tools (default), `full` = all tools |
| `OPENDAW_SERVE_MODE` | `static` (Docker image) | `static` = serve a pre-built host via `scripts/serve_static.py` (no Node); `vite` = Vite dev server |
| `OPENDAW_STATIC_DIR` | `/opendaw/headless-daw/dist` | Directory served in static mode |
| `MCP_TRANSPORT` | `stdio` | `stdio` or `sse` |
| `FASTMCP_HOST` / `FASTMCP_PORT` | `127.0.0.1` / `8000` | SSE bind address |
| `NODE_BIN_DIR` | — | Prepended to PATH for Vite lookup (vite mode only) |
## Docker
```bash
docker build -t opendaw-mcp .
docker run --rm -p 8080:8080 opendaw-mcp
```
The image builds the openDAW headless host ([openDAW-headless](https://github.com/andremichelle/openDAW-headless)) from source, serves its static build via `scripts/serve_static.py`, and runs the server in SSE mode on `:8080`. There is no Node.js in the runtime image; give the container at least 1 GB RAM for comfortable rendering.
## Development
```bash
pip install -e ".[dev]"
python -m pytest tests/ -q
ruff check server.py opendaw_mcp
```
See [ARCHITECTURE.md](ARCHITECTURE.md) for internals and [TOOL_CATALOG.md](TOOL_CATALOG.md) for the full tool list.
## License
Apache-2.0 — see [LICENSE](LICENSE).
TDQS
Scored across 515 tools
Many tools have overlapping purposes: the chord-progression family (create_chord_progression, create_chord_pads, create_voice_led_progression, create_arpeggiated_progression, create_harmonic_arrangement), the song-builder family (create_genre_sections, create_song_with_variations, create_full_genre_pipeline, create_modulated_song, create_arrangement_variation), and the analysis family (analyze_track, analyze_spectrum, analyze_stereo, analyze_dynamics, analyze_mix, analyze_phase, detect_problems) all blur together. Composite tools that duplicate smaller tools (transcribe_audio vs transcribe_drums+transcribe_melody; analyze_track vs detect_bpm+detect_key+measure_lufs) compound the ambiguity. Individual descriptions are detailed, but an agent cannot reliably distinguish which of dozens of near-synonym tools to select.
The vast majority of the 515 tools follow a clean snake_case verb_noun pattern with the mcp_opendaw_ prefix (create_drum_pattern, set_track_volume, list_automation_events). Minor deviations exist: engine_panic/engine_sleep/engine_wake use noun_verb while start_engine uses verb_noun, and duplicate_audiounit/transfer_audiounit spell it as one word while delete_audio_unit uses the underscore. The pattern is predictable enough to navigate, but these inconsistencies stand out at this scale.
515 tools is an extreme mismatch for any MCP server, far beyond even the 50+ threshold described as extreme. The count is inflated by near-duplicate families (30+ genre arrangement tools, 20+ percussion pattern tools, 15+ analysis tools) and multiple composite tools that repackage existing ones. This size will flood an agent's context window and create selection overhead that outweighs the benefit of any individual tool.
The surface covers the full DAW lifecycle comprehensively: project management, transport, track/unit CRUD, note and region editing, effects and sends, automation, MIDI/audio I/O, rendering in multiple formats, audio analysis, transcription, stem separation, and even music-theory composition (fugues, chaconnes, polyrhythms, world percussion). No major dead ends exist - every operation an agent would need for a produce-from-scratch-to-mastered workflow is present, often with redundant multiple approaches.