Skip to main content
Glama
README.md
# 🎵 Orpheus

Keeps Claude in sync with your REAPER session.

Orpheus is an [MCP](https://modelcontextprotocol.io) server that connects Claude (Claude Code,
Claude Desktop, or any MCP client) to a live [REAPER](https://www.reaper.fm/) session.

REAPER is home base. Orpheus reads the live project (tracks, tempo map, markers, regions, what's
playing), notices what you change by hand, and everything it does lands back in the project as
editable tracks, MIDI, markers and effects, on REAPER's own bars and beats. Your Google Sheet
stays in step: sections and chords from the sheet become markers and regions, and changes in
REAPER can flow back to the sheet.

On top of that, it listens to your project and to audio you own (tempo, key, chords, sections,
stems, lyrics and sound character, each with an honest confidence), explains what it hears in
plain language, and works in your session: building tracks, writing MIDI, arranging songs,
setting effects, and (optionally) rendering a rough sung sketch with YuE2. It asks before it
changes anything, and every change can be undone.

It's built for one songwriter-producer working in REAPER, with lyrics in Google Sheets.

> **Status (2026-10-27):** early, pre-alpha, not on PyPI yet. It has 70 tools in the default profile
> (fewer on a base install without the `[analysis]` extra; 72 with YuE2 switched on), 1364 passing
> Python tests and 555 Lua checks in 8 suites (ruff and mypy clean). Much of it was used for real
> in July on REAPER 7.78 with a song the owner owns; the rest is tested against a behavioural fake
> of REAPER. [What works today](#what-works-today) says which is which. Change reports,
> meter-aware bars and the bridge's automatic start were checked live on REAPER 7.83 on 10-25;
> tempo-map writing, sketches in parts, the instrument library and effect recipes (10-27) are
> built and tested but not yet checked live; sheet sync comes later.

## What you can ask

- *"What key and tempo is this song, and where does the chorus start?"*
- *"Split the vocals out of this mp4 I made and put the stems on tracks."*
- *"Where in the song does the hook come back?"*
- *"Here are my lyrics and chords from the sheet. Lay out the song: verse, pre-chorus, chorus, bridge."*
- *"Add a bass line and a half-time drum part under the verse."*
- *"Make the outro vocal sound like it's coming through a telephone."*

## What works today

### Listen

All local, on audio you own:
- tempo, beat grid, downbeats, key, loudness and sections (`recon_reference`);
- an instrument-activity timeline (`instrument_timeline`);
- chords (`get_chords`): an always-on baseline plus an optional model lane;
- stem separation with quality gates and a retry ladder (`separate_region`, `verify_stem`);
- sound character: spectrum, dynamics, stereo, reverb, pitch (`characterize`);
- lyrics with word timings, and "find where this line is sung" (`transcribe_lyrics`, `locate_lyric`);
- comparing two sections of a song that should match (`compare_sections`);
- one entry point that routes a question to the right analysis and reports what it could and
  couldn't measure (`analyze_reference`).

It also reads your own project's MIDI for key, harmony and groove (`build_project_spec`,
`analyze_harmony`, `analyze_groove`).

### Stay in sync with the session

- `get_project_timeline`: the open project's name, every tempo and time-signature change, all
  markers and regions with bar and beat as REAPER's ruler shows them, and the transport.
- `project_changes`: what changed since the last check, in plain words ("Track 'Gtr' renamed
  to 'Gtr DI'", "New MIDI item on 'Bass' at bar 9"), kept per project across restarts.
- Anything placed "at bar N" follows REAPER's own tempo and meter map.
- `set_tempo_map`: tempo and time-signature changes at any bar, including tempo that glides
  from one change to the next (a slow-down), in one undo step.
- `get_connection_status` reports which project is open (heartbeat v2).

These are tested against the fake and the Lua suite; the live check in REAPER is still owed.

### Explain

Analyses return measured numbers with confidence values, which lets Claude explain why
something sounds the way it does (for example "the low band is 6 dB hotter than the
reference"). `compare_character` turns the difference between two sounds into concrete effect moves, using
14 rules.

### Work in the session

- Projects: `new_project` opens an empty tab for a new song and `save_project` saves it (in place,
  or as a path that then becomes its file).
- Tracks, tempo, meter, transport, and MIDI written in beats, never ticks (a note written at beat B
  reads back at beat B).
- Composing: chord progressions, bass lines, drum patterns, melodies, humanizing, whole sections,
  and `arrange_song` for a full sectioned song with markers and lyric lines.
- Effects: add by name, set and read parameters, using calibrated maps for REAPER's stock plugins
  and Surge XT.
  `remove_fx` takes one off. `get_fx_params` shows each value as the plug-in does ("-9.0 dB"),
  and effect recipes dial every value in against that display, so a wrong map can't put
  a delay at 317 ms when the recipe says 95.
- Effect recipes: `list_effect_recipes` and `apply_effect_recipe` put a named chain on a track
  (PA announcement, telephone, station hall, tape wobble, lo-fi radio, distant, intimate vocal),
  built from REAPER's own plugins. Every effect and setting comes back, and anything it couldn't
  do is listed. Tape wow and flutter come from Orpheus's own JSFX (MIT), which
  `install_orpheus_jsfx` copies into REAPER's `Effects/Orpheus` folder without overwriting a copy
  you changed.
- Mixing: `render_mix_region` bounces the whole mix (the master chain on, listening solos
  ignored) so loudness and tone can be measured, and `master` is a track name for mastering
  effects.
- Audio: import your stems as time-locked tracks, render a track region to WAV, and clone a take
  onto new tracks (for doubles). `align_vocal_take` puts a sung take of a lead sheet on the
  bars phrase by phrase, without stretching it, and `align_stem_take` puts the take's band stems
  on the bars with REAPER's stretch markers (see "Lining a take up with the bars" below).
- Instruments: Orpheus prefers instruments you have installed, and `suggest_free_vst` recommends
  free ones. An optional sound pack (`install_sound_pack`, about 24.5 MB) adds three public-domain
  FreePats instruments (guitar, bass, upright piano) that play through REAPER's own sampler.
- Niche instruments: `find_instrument("celesta")` looks through your installed plugins, the sound
  pack, a library of 16 public-domain (CC0) sample instruments, and the free-plugin list, and says
  what's nearest when something isn't available. The library has glockenspiel, vibraphone,
  tubular bells, wind chimes, kalimba, harp, marimba, xylophone, solo cello and violin, string
  sections, a soft upright, an old honky-tonk piano and water glasses, each pinned to a GitHub
  commit and checked file by file. `fetch_instrument` shows the size and licence and downloads
  only after you say yes; `load_library_instrument` plays it through REAPER's sampler.

These are tested against the fake; a live listen in REAPER is still owed for the recipes, the
tape-wobble JSFX and the library instruments.

More bridge commands were built and used live in July but don't have MCP tools yet: moving
and deleting tracks; regions; automation envelopes; trimming, windowing and nudging items;
factory presets; refreshing media and peaks; and instruments built from your own samples.
(Renaming, colouring, muting and folders have tools now: `set_track_params`, `group_tracks`.)

### Verified on real REAPER

In July 2026, on REAPER 7.78: the bridge, the effect maps, region rendering,
stem import, item cloning, those fifteen bridge commands, hot reload, and analysis of an owned
200-second song (separation, lyrics, sections). The full-song composer and the chord and lyric
quality still need a live check by ear. The [dev-log](docs/dev-log.md) has the details.

## How a song gets made

1. You write lyrics, sections and chord charts in your Google Sheet.
2. Claude reads the sheet through the Google Drive connector. Orpheus never signs into Google;
   it only gets text.
3. Orpheus lays the song out in REAPER: section markers, chords, bass, drums, a melody, and your
   lyric lines on the markers.
4. You record. Orpheus analyses the take, and Claude suggests changes. You approve each one.

Orpheus reads your sheet's own notation: chord charts (`Am / Fmaj7 | C / E (x4)`, slash
chords, holds, `(stop)`) and bass tab (`A0 -  E1 -`). A section, given as written plus a melody
Claude writes with you, becomes a **lead sheet**: `arrange_lead_sheet` lays it into REAPER (markers,
chords, bass riff, melody, drums, lyric markers), and `export_yue2_score` turns it into a score for
YuE2. With the optional YuE2 backend switched on (below), `render_sketch` sings chosen sections
at the section's bar, so you can hear the idea over the arrangement before you record it. A YuE2
take is one stereo WAV with its band, melody and voice effects baked in, so each take is then
**unpacked** into a folder of tracks you can see and edit (below): the vocal lined up on REAPER's
bars, the melody it actually sang as MIDI, the raw mix, and each stem that plays.
`align_vocal_take`, the lining-up step, also works alone on any sung take of a lead sheet and
needs no YuE2.

A section can change the song's meter, tempo or key (a 6/8 bridge, a final chorus up a step, an
outro that slows down with `ramp_to_bpm`). `arrange_lead_sheet` writes those changes into
REAPER's tempo map. YuE2 sings meter and key changes inside one score; a score has one tempo, so
where the tempo changes the sketch is sung in parts, all on the take's one track.

## What it won't do

- Fetch, rip or capture music you don't own. Analysis runs only on files you give it.
- Need an account, a subscription or a paid API. Everything runs on your machine.
- Master a track for release, or replace your ears.
- Change your project without asking first.

## Not built yet

- Sheet and REAPER in step: sheet sections and chords as markers and regions, and REAPER changes
  written back to the sheet (Claude does the sheet side, with your yes).
- "Sing it to me": notating a melody from a scratch vocal take.
- Beat-map export for cutting music videos in Premiere (OpenTimelineIO).
- Edit plans applied in one undo step (`apply_changes`) and style-based suggestions
  (`recommend_changes`). Both are stubs, registered only in the `full` profile.
- Master rendering and audit (`render_project`, `render_and_audit`) and mix balancing.

## Optional: non-commercial backends

Some useful models allow only non-commercial use: YuE2 (sung song sketches), LarsNet (drum
splitting). Orpheus is MIT, so these are off by default. Switch each one on by name:

```json
"env": { "ORPHEUS_NC_BACKENDS": "yue2" }
```

Their weights are never bundled. You download them yourself, under their own licence (CC BY-NC
4.0 for YuE2), and Orpheus talks to them as a separate program.

**YuE2 setup.** Build [yue2.cpp](https://github.com/ServeurpersoCom/yue2.cpp) (MIT) with CUDA and
put the backbone (`YuE2-3B-Q8_0.gguf`, 3.8 GB) and the VAE (`YuE2-Vae-F32.gguf`, 0.5 GB) in its
`models` folder, laid out as `~/.orpheus/yue2/yue2.cpp/build/Release/yue-synth.exe` and
`~/.orpheus/yue2/models/`. [`docs/pins/2026-10-yue2-backend.md`](docs/pins/2026-10-yue2-backend.md)
has the build commands and file hashes. On an RTX 3080 a sketch takes about half its length to
render and peaks near 6–7 GB of VRAM; Orpheus's own GPU work waits while it runs. YuE2 often
keeps playing past your last bar, so a sketch stops 4 s after it with a 2 s fade you can drag. Sketches are
saved under `~/.orpheus/sketches/`, one folder per render with the request, the WAV, YuE2's
replay file and its log.

`render_sketch` exposes YuE2's whole request; the defaults sing exactly as before:

| Option | What it does |
|---|---|
| `takes` (1-8) | different performances, one track each |
| `variations` (1-4) | the same performance re-sung under new noise from its replay file (quick) |
| `steps` | quality of the sound stage (default 32; more is slower) |
| `guidance` | how closely YuE2 follows the lyrics and style |
| `melody_sampling`, `sound_sampling` | temperature, top-p, top-k, repetition penalty: how adventurous each stage is |
| `adapters` | LoRA add-ons from `yue2.cpp/adapters`, each with a strength (`list_yue2_adapters`) |
| `compose_melody` | YuE2 writes its own tune to your lyrics; `planned_score` comes back for `import_yue2_score` (pass the same `style`) |
| `replay_of` | re-sing an earlier sketch folder with a new seed or more steps, at the same bar |
| `measure_drift` | separate each take's vocal and report the tempo it was really sung at and how far it got ahead and behind (about a minute per 4-minute take) |
| `unpack` (on by default) | each take into its own folder of tracks (below); `False` leaves the raw take alone |

Each render takes about half its length on the 3080, and there is one per part, take and
variation.

**Unpacking a take.** After the renders, each take goes in a folder `Take #<seed> (YuE2)`:

| Track | What it is |
|---|---|
| `· vocal on the bars` | the vocal, separated and lined up phrase by phrase; the one track left playing |
| `· sung melody (MIDI)` | what the take actually sang, as notes on the bars (ReaSynth), to compare with your melody or copy from |
| `· raw mix (YuE2)` | the take as YuE2 rendered it |
| `· drums`, `bass`, `guitar`, `piano`, `other (YuE2 timing)` | each stem that plays, in YuE2's own timing; an empty one (no drums in the take) gets no track and a warning |

Coloured regions mark where YuE2's voice changes on its own: much wider than usual (doubled or
spread) or filtered (a phone or radio sound). Everything but the lined-up vocal is muted, nothing
is deleted, and each take's result has `sung_vs_written`: per section, how many written notes it
sang as written, how many it changed, dropped or added (the same count as `align_vocal_take`'s,
below). Unpacking adds about two minutes per 4-minute take (one separation, one pitch track); a
take whose tune YuE2 wrote (`compose_melody`) is left as rendered.

Tracks have names that say what they are, so `set_track_params` can rename, colour (`color`,
"#RRGGBB") and mute (`mute`) a track, and `group_tracks` puts tracks in a folder.

**Changing a section's lyrics.** Two steps, so a rewrite costs a section, not a song:

1. `fit_lyrics(lead_sheet, section, lyrics)` checks the new lines against the section's melody
   before anything renders: each line's syllables against the notes its old line had (words the
   sheet already splits are counted its way, others by spelling rules and listed as guessed),
   and whether lines that rhymed still do (`rhyme`, `near` or `no`, a hint for your ear). A line
   a syllable long or short gets a proposal: its longest note split in two, or two short
   neighbours merged, never its last note (the rhyme). It changes nothing; the proposal goes into
   the sheet only with your yes.
2. `resing_section(lead_sheet, section, take, vocal_track, midi_track)` re-sings just that
   section. YuE2 continues the take from just before the section, from the take's own codes, so
   it stays in that take's voice and sound, and sings the section's new words. The new vocal is
   separated, lined up on the bars and spliced into the vocal track's item at the quietest moment
   near each edge, with 30 ms crossfades. The splice is one undo step and keeps the track's
   effects and fader; the sung-melody MIDI is updated for the section. A section whose syllables
   don't spell its lyrics is refused before the GPU runs. If it's the first section the take
   sang, there's nothing to continue from, so it's sung fresh with the take's seeds and the voice
   may differ (it says so). Live, re-singing Chorus 1 after the pre-chorus took 44 s.

**Lining a take up with the bars.** YuE2 doesn't keep its score's tempo. Take 8602 of "Attention,
Please" sang at about 88.8 BPM against the score's 86, got 4.2 s ahead by the bridge, fell behind,
then caught up. One offset can't place a take like that. `align_vocal_take` takes a sketch WAV
(its vocal is separated first) or any vocal stem, plus the lead sheet (or `lead_sheet_path`, its
JSON file). It maps the written melody onto the sung pitch, cuts the vocal at its breaths into
pieces of 2.5 s at most, and moves each piece whole to where REAPER's own bars put it, so a 6/8
bridge and a slowing outro come out right. Nothing is stretched. It writes `<sketch> aligned.wav`
next to the sketch and changes the project only with `import_to_reaper=True` (a new track at the
first sung bar). Pieces sung where the score has no melody, or that the score has no room for (a
line sung twice), are left out, and the result says where. On take 8602, 55 of 56 eight-second
windows land within 0.1 s of the melody. The exception is one held note in the first Tag, which
the earlier hand alignment also missed. Inside a piece the take keeps its own pace, so
in a steep ramp (90 to 70 BPM) its notes can sit up to about 0.2 s off at a piece's edges.

**What the take actually sang.** A singer, or YuE2, sometimes changes the tune. With `midi=True`,
`align_vocal_take` reads the notes off the lined-up vocal and compares them with your melody note
by note:

| In the result | What it is |
|---|---|
| `sung_vs_written` | per section: written notes sung as written (`same_note`), sung on another pitch (`changed`, with `semitone_off` and `octave_off` among them), not sung (`dropped`: a rest, a breath or a slide where a note was written), notes sung that aren't written (`added`: a note in a rest, a run, a held note the sheet doesn't have), and `ornaments` (scoops into a note, glides, fall-offs, turns) |
| `sung_melody.changes` | each changed, dropped or added note with REAPER's bar and beat, the written and sung note (`E4` -> `F4`) and the section; the first 50, all of them in the JSON written next to the take |
| `sung_melody.notes`, `range` | how many notes were sung, lowest and highest |

A written note counts as sung when a note of its pitch covers a good part of it or starts within
0.15 s of it (a little early or late), so one note sung in two breaths, or two repeated notes sung
as one, is still the same note. A short note (under 0.25 s) joined to the melody without a breath
is an ornament, not an added note; blips under 120 ms aren't counted. On take 8602 of "Attention,
Please" that reads 497 of 559 written notes as sung, 45 changed, 17 dropped, 29 added and 45
ornaments (YuE2 often scoops into a note from a step below), with the Bridge changed most (76%
as written) and the Final Chorus and Outro not at all. With `import_to_reaper=True` the notes
also go on a new muted MIDI track
`<aligned file> · sung melody (MIDI)` under the vocal, with ReaSynth so it plays when you unmute
it. The notes sit on REAPER's own bars and beats, so they sound where the vocal sings them even
where REAPER's meter differs from the sheet's; a note sung before the first bar starts the MIDI a
bar early. The JSON written next to the take keeps every note, so nothing is lost without
the import.

A band never pauses, so its stems can't be cut at breaths. `align_stem_take` takes the same
sketch WAV and lead sheet and puts the take's drums, bass, piano, guitar and other stems on
REAPER's bars with REAPER's own stretch markers, pitch kept: a marker on every bar line at the
moment of the take where that bar line was played, and one on every beat of a bar where REAPER
ramps. All the stems share one fit, so they stay together, and the markers stay on the items
where you can see and drag them. Where the bar lines were played comes from the vocal's notes
against the written melody, fine-tuned to the drums' hits nearest each beat (an eighth in 6/8).
A take with no melody is followed by its beats alone, counted from its first bar; listen to the
first bars. Each stem gets a new track, 'Take #8602 · drums on the bars', and they share a
folder; the unpacked '(YuE2 timing)' tracks stay as they are. It uses the stems unpack separated
(or separates the take once) and writes `<sketch> stretch.json` with every bar line and marker.
On take 8602's Chorus 1 in REAPER, the rendered drums sit a median 5 ms from REAPER's beats, 97%
within 30 ms (left in YuE2's timing they started half a second late). `timing="beats"` only
counts beats, and on the full 3-minute take it lost count by whole beats through the breaks, so
keep it for short takes with no melody.

Write the sheet's melody at the pitch you want to hear. YuE2 writes a male voice an octave above
how it sounds, the way a tenor part sits in treble clef, so when the style names a male voice the
score goes to YuE2 an octave up and the singer lands on your notes. Set `yue2_vocal_shift` on the
sheet to override it (`0` sings a male voice an octave under the sheet). A section with lyrics but
no melody, such as a PA announcement over a held chord, keeps its words in the sheet for the
markers, but YuE2 isn't given them: it sings the score note by note.

## Settings

Set these in the `env` block of your MCP client config.

| Variable | Values | What it does |
|---|---|---|
| `ORPHEUS_TOOLSET` | `default`, `explain`, `full` | Which tools Claude sees. `full` adds the not-built stubs. |
| `ORPHEUS_ASR_DEVICE` | `auto` (default), `cpu`, `cuda` | Where lyric transcription runs. `auto` uses CUDA only after a test run in a separate process succeeds, so a broken cuDNN setup falls back to CPU instead of crashing the server. |
| `REAPER_MCP_BRIDGE_DIR` | a folder | Where the bridge's request and response files live (default `~/.orpheus_bridge`). |
| `ORPHEUS_AUTOSTART_BRIDGE` | `1` (default), `0` | Whether a call starts the bridge in an open REAPER by itself. |
| `ORPHEUS_REAPER_EXE` | a path | The REAPER program, if it isn't in the usual install folder. |
| `ORPHEUS_NC_BACKENDS` | e.g. `yue2` | Switches on named non-commercial backends; `yue2` adds `render_sketch`. |
| `ORPHEUS_YUE2_DIR` | a folder | Where yue2.cpp and the YuE2 weights live (default `~/.orpheus/yue2`). |
| `ORPHEUS_SKETCH_DIR` | a folder | Where rendered sketches are saved (default `~/.orpheus/sketches`). |
| `ORPHEUS_LIBRARY_DIR` | a folder | Where fetched library instruments live (default `~/.orpheus/library`). |
| `ORPHEUS_REAPER_RESOURCE_DIR` | a folder | REAPER's resource folder, if `install_orpheus_jsfx` can't find it. |

## Install

> Not published yet. These are the planned install paths once `v0.1` is on PyPI.

```bash
# 1. Run the server
uvx orpheus-mcp

# 2. Install the bridge into REAPER (one-time); from then on it starts with REAPER
orpheus-mcp install-bridge
```

Then add it to your MCP client, for example Claude Desktop's `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "orpheus": { "command": "uvx", "args": ["orpheus-mcp"] }
  }
}
```

Open REAPER and ask Claude to *"check the Orpheus connection."* If REAPER was already open,
Orpheus starts the bridge in it the first time Claude needs it (or run `orpheus-mcp
start-bridge`). Per-OS steps: [`docs/installation.md`](docs/installation.md). Working from source:
[`CONTRIBUTING.md`](CONTRIBUTING.md).

## How it works

Orpheus is a Python [FastMCP](https://gofastmcp.com) server. It never calls REAPER's API
directly. It writes JSON request files that a Lua script running *inside* REAPER picks up,
executes and answers. The bridge is hardened: atomic writes, a heartbeat, a fixed table of
commands (nothing evaluated from the wire), per-call caps, and hot reload of new commands without
restarting REAPER. Claude talks in beats; all tick and tempo math happens in the bridge. Tools that
change the project are marked `destructiveHint`, so your client can ask you before each one. Engines with
clashing dependencies (audio-separator, basic-pitch) run in their own environments as separate
processes. More: [`docs/architecture.md`](docs/architecture.md).

> **Why not `python-reapy` or OSC?** REAPER's OSC can't pass arguments to custom actions, so it
> [can't create tracks or write MIDI notes](docs/architecture.md#why-not-osc). `python-reapy` is
> effectively unmaintained and throttles to about 30 to 60 calls a second. A Lua loop inside REAPER
> avoids both.

## Credits

Orpheus reimplements patterns from these projects under MIT; it does not copy GPL-licensed code.
Per-project notes: [`docs/frontier-analysis.md`](docs/frontier-analysis.md).

- [shiehn/total-reaper-mcp](https://github.com/shiehn/total-reaper-mcp): the file-JSON bridge pattern and tool profiles.
- [xDarkzx/Reaper-MCP](https://github.com/xDarkzx/Reaper-MCP): bridge hardening (heartbeat, static dispatch, per-call caps).
- [ahujasid/ableton-mcp](https://github.com/ahujasid/ableton-mcp): the beats-not-ticks note model and tool granularity.
- [dschuler36/reaper-mcp-server](https://github.com/dschuler36/reaper-mcp-server): the typed project tree and objective audio checks.
- [jarmstrong158/waveform-MCP](https://github.com/jarmstrong158/waveform-MCP): the `CompositionSpec` idea and the primitives-vs-composers split (patterns only; its code is GPL-3.0).
- [bonfire-audio/reaper-mcp](https://github.com/bonfire-audio/reaper-mcp): chord and drum primitives, headless render recipes.
- [music21](https://music21.org) and [asume21/music-theory-mcp](https://github.com/asume21/music-theory-mcp): the theory layer.
- [AI TrackMate](https://arxiv.org/pdf/2412.06617): the pattern of analysing, writing a readable report, then giving feedback.
- [Matchering](https://github.com/sergree/matchering) (GPL-3.0): the likely engine for future master matching. It will be an optional install, not a dependency.

Model credits and licences for the analysis engines are in
[`data/model_registry.json`](data/model_registry.json) and [`docs/pins/`](docs/pins/).

The sound pack and the instrument library fetch public-domain (CC0) samples on request; none are
bundled. Thanks to [FreePats](https://freepats.zenvoid.org), Versilian Studios
([VCSL](https://github.com/sgossner/VCSL) and [VSCO 2 Community Edition](https://github.com/sgossner/VSCO-2-CE)),
and Karoryfer Samples with bigcat instruments
([cello](https://github.com/sfzinstruments/karoryfer-bigcat.cello)). Each instrument's source and
licence are in [`data/instrument_library.json`](data/instrument_library.json).

## License

[MIT](LICENSE) © 2026 Mal0ss.

TDQS

B3.4/5.0

Scored across 32 tools

Disambiguation5/5

Each tool has a clearly distinct purpose, from analysis (analyze_audio_character, analyze_groove) to editing (transpose_notes, quantize_notes) and application (apply_changes, apply_master_match). No overlapping functionality; even similar actions like rendering are differentiated by scope (project, stems, audit).

Naming Consistency5/5

All 32 tools follow a consistent verb_noun naming pattern with underscores, e.g., create_track, get_project_info, set_tempo. Verbs are reused predictably (analyze_, get_, set_, render_) making the API easy to navigate.

Tool Count2/5

At 32 tools, the server is over-scoped for typical use. While each tool is justified by its description, the sheer number increases cognitive load and selection complexity. A leaner set (around 20) would be more manageable.

Completeness4/5

Covers a broad domain: project info, MIDI operations, FX management, transport, analysis, and recommendations. Minor gaps exist (e.g., explicit parameter automation, audio item editing), but core workflows for the Orpheus intelligent assistant are well-supported.