hermes-daw
by Zabat-code
README.md
# Hermes Music + DAW
Python MIDI composition with executable arrangement checks, plus a headless
MCP server for offline mixing and mastering. CPU only; no DAW window, audio
interface, GPU, model download or cloud account required.
**Español:** [README.es.md](README.es.md)
**Start here:** [agent protocol](PROTOCOL.md) · [architecture](docs/ARCHITECTURE.md) ·
[documentation index](docs/README.md) · [contributing](CONTRIBUTING.md).
This is an early open source toolkit. The composition checks have regression
coverage; the DAW is a hardened prototype, with tests for all ten tools and a
real stdio MCP session. Neither component decides whether music sounds good.
| Component | What you get |
| --- | --- |
| `hermes-music` | MIDI composition, eight arrangement gates and SHA-256 delivery receipts |
| `hermes-daw` | Ten MCP tools for rendering stems, measuring audio, mixing and mastering offline |
The guard exists because written corrections failed to prevent the same defects
in the next composition. It checks a defined structural contract before delivery;
it cannot certify timbre, genre fidelity or listening quality.
## Quick start: install, test, try
From a downloaded or cloned checkout, on Linux with Python 3.12:
```bash
cd hermes-music-daw
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[dev]'
sudo apt install fluidsynth fluid-soundfont-gm ffmpeg
python scripts/check_install.py
python -m pytest tests/ -q
python examples/01_compose.py --work output/demo
python examples/02_audit.py --work output/demo
python examples/03_mix_and_master.py --work output/demo
```
The example produces an audited MIDI, six WAV stems, a mix, a master, an OGG
and JSON measurements. Use a fresh output directory for each run. FluidSynth,
FFmpeg and a SoundFont are needed for audio and the full integration tests;
the MIDI gates do not require an audio device. See below for configuration and limits.
## Why the guard exists
The same bad arrangement happened twice: mechanical drums, overlapping attacks,
flat dynamics, crowded instruments and GM guitars that sounded like an 8-bit
mockup. The correction was already written in Markdown. It did not change the
next composition.
The response was executable: **read → decide → compose → audit → publish**.
Eight arrangement gates abort a defective delivery with exit code 1. An external
audit then found faults in the author's own v2; those were corrected too.
The lesson is the reason for this repository: documentation needs enforcement
at the point where an artifact is delivered.
The guard records the exact MIDI's SHA-256, the plan, required readings and guard
code. Editing the MIDI invalidates its receipt. This is an integrity record,
**not a digital signature, aesthetic certificate or security sandbox**. Arbitrary
code can bypass it; an agent must use the prescribed entry point.
## Install
Tested with Python 3.12.3 on Linux. The main dependency versions are pinned in
[requirements.txt](requirements.txt): Mido 1.3.3, NumPy 2.5.3, Pedalboard 0.9.26,
FastMCP 4.1.1. The list does not lock transitive dependencies.
`pip install -e .` installs the runtime package without the pytest extra. The
import namespace is `hermes_music.scripts`; console commands include
`hermes-music`, `hermes-daw`, `hermes-mix`, `hermes-music-audit`,
`hermes-music-guard` and `hermes-music-check`. Direct script execution also works.
SoundFont discovery checks `MIDI_SOUNDFONT` first, then common system locations,
including FluidR3_GM and TimGM6mb. An explicitly invalid override is an error.
Executables are discovered on `PATH`; `FLUIDSYNTH`, `FFMPEG` and `FFPROBE` can
override them. No user-specific paths are required.
```bash
export MIDI_SOUNDFONT=/path/to/your/font.sf2 # optional when auto-detected
```
Offline FluidSynth subprocesses default `SDL_AUDIODRIVER` to `dummy` to avoid
audio-device enumeration hangs in containers. This does not affect file synthesis.
Other platforms and dependency combinations have not been verified here.
## Run the small example
These scripts use the actual guard and audio engines, not placeholder media.
Run them in order from the checkout, using a fresh output directory on each run:
```bash
python examples/01_compose.py --work output/demo
python examples/02_audit.py --work output/demo
python examples/03_mix_and_master.py --work output/demo
```
The result is a 12-bar, 18-second MIDI with three contrasting sections, six
stems, a mix, a master, an OGG export and JSON measurements. The audio retains
FluidSynth's release tail. The full required readings and guard output are in
`output/demo/composition.log`. Existing guard deliveries are never overwritten.
Listen to [sample.ogg](examples/sample.ogg), inspect [sample.mid](examples/sample.mid),
and see [sample provenance](examples/README.md). These are GM structural demos;
listening quality has not been certified. Actual run output and verification
details are recorded in `docs/`.
For your own dense arrangement, write and review a decision plan first, then
run your composer through the guard. The reference is a full 120-bar example:
```bash
python scripts/example_dense_arrangement.py --plan plan.json
# Review/adapt the plan AND composer before creating a new piece.
python scripts/composition_guard.py plan.json --out piece.mid -- \
scripts/example_dense_arrangement.py --out '{draft}'
python scripts/audit_arrangement.py piece.mid --json review.json
python scripts/composition_guard.py --verify piece.mid
```
Follow [PROTOCOL.md](PROTOCOL.md) for rendering, mixing, mastering and publication.
Low-level `hermes-music recipes`, `compose`, `gen`, `validate`, `render` and
`rebuild` remain available. `validate` alone does not approve an arrangement.
Genre plans from `genre_engine.py` are harmonic guides, not finished songs.
## Architecture and file map
```text
readings + decision plan + composer
↓ composition_guard (subprocess, temporary MIDI)
audit_arrangement: 8 gates
↓ exact MIDI + SHA-256 receipt
FluidSynth / SoundFont → instrument WAV stems
↓ mix_engine: role chains + stereo balance + bus
daw_mcp.master: bus chain + FFmpeg loudnorm
↓ WAV → OGG → release_check → human listening
```
| File | Purpose |
| --- | --- |
| `PROTOCOL.md` | Ordered agent workflow, failures and repairs |
| `scripts/hermesmusic.py` | MIDI events, patterns, SongSpec, validation, rendering and CLI |
| `scripts/audit_arrangement.py` | Eight fail-fast arrangement gates |
| `scripts/composition_guard.py` | Required readings, plan contract and hash receipt |
| `scripts/example_dense_arrangement.py` | Note-by-note reference composition |
| `scripts/genre_engine.py` | Experimental harmonic-form planner |
| `scripts/mix_engine.py` | Role/profile DSP chains, stereo balance, duration handling |
| `scripts/daw_mcp.py` | Ten MCP tools; same functions are usable from Python |
| `scripts/audio_utils.py` | Audio validation, discovery, FFmpeg measurements and subprocess errors |
| `scripts/check_install.py` | Dependency, binary, SoundFont and resource smoke check |
| `references/` | Genre data, theory, rendering and SongSpec examples |
| `examples/` | Three executable stages and a small MIDI/OGG sample |
| `tests/` | Composition regressions, DSP checks and real MCP calls |
| `docs/` | Current guides and dated historical evidence |
| `SKILL.md` | Detailed composition workflow and MIDI API; the historical integration guide is not bundled |
| `templates/songspec.json` | Low-level SongSpec schema example |
The legacy dembow, harmonic-circle and MIDI-effect scripts remain in `scripts/`
as experimental standalone utilities with known implementation defects; see the
[MIDI-effect reference](references/effects_mapper.md). They do not issue guard
receipts and are outside the tested composition/audio workflow. `build_index.py` is
a Hermes-specific adapter requiring a separate skills-index plugin.
## MCP tools and clients
Start with `list_profiles`, then follow the protocol. Audio paths are local to
the machine running the server. WAV is the processing format; `analyze_audio`
and `release_check` can also inspect an OGG supported by the installed decoder.
| Tool | Use / result |
| --- | --- |
| `list_profiles` | Supported roles and complete DSP settings |
| `render_stems` | MIDI → named WAVs; audit first; requires FluidSynth and SoundFont |
| `analyze_audio` | Sample peak, RMS, octave energy and stereo correlation |
| `analyze_masking` | Heuristic ranking of spectral overlap between stems |
| `auto_mix` | Role processing, stereo balance and bus chain; output metrics |
| `apply_eq` | Targeted EQ; before/after metrics |
| `apply_comp` | Targeted compression; before/after metrics |
| `master` | Profile chain + two-pass FFmpeg loudnorm; measured LUFS/TP and target status |
| `compare_to_reference` | Candidate-minus-reference level and band deltas |
| `release_check` | Measured loudness/true peak/LRA, issues and ready/needs_work |
The MCP exposes the audio stage. Composition and guard verification run through
the CLI. MCP render tools can process arbitrary MIDI; they do not implicitly
certify it. Bad paths, corrupt/empty/silent audio and unknown profiles return
clear tool errors. All processing occurs in memory; long stems use more RAM.
After installation, this configuration launches the package from any working
directory. Replace the interpreter path with the absolute path of your venv's
Python. Optional `env` settings must be valid on the server host.
```json
{
"mcpServers": {
"hermes-daw": {
"command": "/absolute/path/to/hermes-music-daw/.venv/bin/python",
"args": ["-m", "hermes_music.scripts.daw_mcp"],
"env": {"MIDI_SOUNDFONT": "/usr/share/sounds/sf2/FluidR3_GM.sf2"}
}
}
}
```
- **Claude Desktop:** Settings → Developer → Edit Config; merge the entry into
`claude_desktop_config.json`, then restart. See the
[official local-server guide](https://modelcontextprotocol.io/docs/develop/connect-local-servers).
- **Cursor:** merge the JSON into project `.cursor/mcp.json` or personal
`~/.cursor/mcp.json`, then restart. See [Cursor's instructions](https://prod.cursor.com/help/customization/mcp).
- **Hermes:** add the following under `mcp_servers` in `~/.hermes/config.yaml`
and restart Hermes. See [Hermes MCP documentation](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/mcp.md).
```yaml
mcp_servers:
hermes-daw:
command: /absolute/path/to/hermes-music-daw/.venv/bin/python
args: ["-m", "hermes_music.scripts.daw_mcp"]
env:
MIDI_SOUNDFONT: /usr/share/sounds/sf2/FluidR3_GM.sf2
```
Configuration formats were checked against those upstream guides. GUI client
connections were not exercised; the automated test performs handshake,
`tools/list` and calls all ten tools over real stdio MCP. The server needs no
HTTP port or authentication setup. It runs with the host user's file permissions.
In a restricted Linux sandbox that denies `socketpair.send()`, set
`HERMES_DAW_STDIO_POLL=1` in the server's `env`. This enables a 50 ms event-loop
timer so thread-based stdio can wake correctly. The local protocol test uses
this compatibility mode for both server and client; normal desktop use does
not require it.
## Mix profiles
`power_metal` and `balanced` are engineering starting points. Stems must use
exact role names; an unknown name aborts instead of silently losing an instrument.
A subset of roles is allowed. Both profiles now include the reference's
`lead_guitar` and `synth_piano`, alongside the original L/R lead roles.
| Setting | power_metal | balanced |
| --- | --- | --- |
| Drums HPF / compression | 35 Hz / -12 dB, 3:1 | 30 Hz / -14 dB, 2.5:1 |
| Bass HPF / low shelf | 40 Hz / +3 dB at 120 Hz | 38 Hz / +2 dB at 100 Hz |
| Rhythm HPF / presence / L-R balance | 90 Hz / +2.5 dB at 2.4 kHz / ±0.55 | 80 Hz / +1.5 dB at 2 kHz / ±0.50 |
| Lead HPF / presence / L-R balance | 200 Hz / +3 dB at 3.2 kHz / ±0.30 | 180 Hz / +2 dB at 2.8 kHz / ±0.25 |
| Piano HPF / level | 180 Hz / 0.45 | 150 Hz / 0.48 |
| Bus HPF / mud / air | 28 Hz / -1.5 dB at 300 Hz / +1.5 dB at 8 kHz | 25 Hz / -1 dB at 250 Hz / +1 dB at 9 kHz |
| Bus trim / sample limiter | -3 dB / -1 dBFS | -3 dB / -1 dBFS |
HPFs reduce low-frequency competition, shelves shape tonal balance, compression
controls dynamics and balance separates doubled parts. These choices require
listening. [Full parameters and interpretation](docs/MIX_PROFILES.md).
## Honest limits
- **GM is a mockup renderer.** It does not reproduce realistic distorted guitars,
palm mute, playing technique, convincing vocals or studio production.
- **The auditor checks a structural contract, not taste or genre fidelity.**
Its dense contract supports 4/4. It intentionally rejects some musically valid
choices; other styles need separately designed and tested contracts.
- **73 genre profiles are provisional and unaudited by listening.** The catalogue
has 100 labels and 104 variants, with 22 direct-source and 5 family-source
profiles. There are only 15 distinct legacy drum grids. The harmonic planner
does not generate a genre's full instrumentation.
- **Masking is heuristic.** Correlated octave energies do not prove that a part
is inaudible. RMS is not LUFS; sample peak is not true peak. True peak and LUFS
are measured separately using FFmpeg.
- **A release verdict is a limited technical screen.** It cannot find every
audible defect, certify dynamics from a single threshold or replace listening.
Mastering targets may be constrained; inspect `target_met` and the final codec.
- **Stem rendering expects one named instrument channel per note track.**
Split multichannel type-0 tracks first. Shared controllers/programs across
tracks are not reconstructed; keep each instrument's controls in its own track.
- **Receipts currently depend on absolute paths and exact code/readings.**
Re-run the guard after moving a checkout or changing its bound files. Hashes
are integrity evidence, not protection against a malicious writer.
- No perceptual reference matching, automated aesthetic judgment, neural audio
generation, real-time DAW session or validated performance benchmark is claimed.
## Tests and license
```bash
python -m pytest tests/ -q
```
Tests generate audio and regression MIDI locally. Audio integration tests need
the system dependencies above; CI installs them on Python 3.12. The original
33 composition tests and 100 catalogue subtests are retained; private desktop
fixtures were replaced with reproducible defect-class fixtures.
Original source: [MIT](LICENSE). **Pedalboard is GPL-3.0** and FluidR3 has its own
upstream license. Neither is relicensed by this project's MIT notice; see
[third-party notices](THIRD_PARTY_NOTICES.md). The SoundFont is not bundled.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues