Let your coding agent use your Analog Rytm MkII with MCP.
Thirty-two semantic tools covering the whole instrument — patterns and p-locks, kit sounds and machines, scenes and performance macros, songs, the sample RAM, and audio capture. The agent reads the device's actual state, proposes a change in musical terms, and commits it on the next beat. You keep playing.
you: give the SD a broken 16th pattern, ghost notes at 40, and swing the closed hats agent: rytm_inspect_pattern A01 → rytm_propose_pattern_delta → rytm_queue_operations at=next_measure → applied on the downbeat, read back, revision 47
Part of the LEMON house · lemon-agent.dev teaches the agent method · lemon.audio is the music side of the house · sibling tools: smpl · vox
The vocabulary is musical intent, not SysEx addresses. Each example below names the tools that actually run — all of them exist today and are certified against hardware.
“what's on A01 right now?”
Returns a compact summary of the pattern — trigs per track, velocities, conditions, microtiming, track lengths, p-locks — small enough to reason about rather than a dump of the whole project.
rytm_inspect_pattern rytm_inspect_kit
“put a four-on-the-floor kick down, hats on the offbeats, and give the snare a conditional fill every 4th pass”
Trigs, velocities, microtiming, and trig conditions written as one validated batch, committed on the next measure so the change lands musically instead of mid-bar.
rytm_propose_pattern_delta rytm_queue_operations
“make the kick hit harder — more overdrive, shorter decay, and detune it down a bit”
Machine selection and per-page parameters on the kit sound: SRC, sample, filter, amp, and LFO pages, by name, with ranges validated against what the connected firmware actually supports.
rytm_apply_operations_now rytm_inspect_track_sound
“build me a scene that chokes everything into the filter, then ride the performance macro up over 8 bars”
All 12 Scenes and 12 Performance macros are addressable with semantic voice and FX lock targets. Definitions are written as revisioned Kit state; activation and macro amounts go out as transient CC/NRPN, exactly as the hardware treats them.
rytm_set_active_scene rytm_set_performance_macro
“take these six samples, put them in RAM, and build a kit around them”
Samples are content-identified so nothing transfers twice, resolved into RAM slots, assigned to sounds, and verified by readback. Slot conflicts are caught before anything is written, not halfway through.
rytm_upload_sample rytm_resolve_sample_ram
“chain A01 into A02 twice, then A03, and mute the toms on the last pass”
Songs as data: rows, pattern chains, repeats, and per-position track mutes across all 17 Song slots — insert, move, copy, or clear them, applied now or on a musical boundary.
rytm_propose_song_delta rytm_inspect_song
“play that for eight bars and record it so we can hear what we did”
Runs the pattern from generated or observed clock and captures a bounded 48 kHz stereo take, checked for silence, clipping, dropped blocks, and duration mismatch — or the full Overbridge stem set if you have it.
rytm_capture_pattern_audio rytm_capture_multitrack_audio
“no, that was worse — put it back”
Restores the raw SysEx captured before the change, across every object it touched.
rytm_rollback_snapshot
Thirty-two tools, MCP-shaped: the adapter exposes
listTools() and callTool() so it mounts into an
MCP host or any agent runtime you already run.
rytm_inspect_device_statethe whole compact picturerytm_inspect_patterntrigs, locks, lengthsrytm_inspect_kitkit and FX staterytm_inspect_track_soundmachine and per-page paramsrytm_inspect_songrows, chains, repeats, mutesrytm_inspect_globalrouting, MIDI, sequencerrytm_inspect_samples+Drive, 127 RAM slotsrytm_describe_capabilitieswhat this firmware supportsrytm_propose_pattern_deltadescribe a pattern changerytm_propose_song_deltadescribe a song changerytm_validate_operationscheck before dispatchrytm_queue_operationshold for a musical boundaryrytm_apply_operations_nowcommit immediatelyrytm_get_eventsacknowledgements, state changesrytm_trigger_trackhit a voicerytm_set_transportstart, stop, continuerytm_change_patternswitch on a boundaryrytm_set_live_parametertrack level, muterytm_set_active_scenescene on/offrytm_set_performance_macromacro amountrytm_upload_samplecontent-identified, no dupesrytm_resolve_sample_ramslot assignment with readbackrytm_clear_sample_ramfree slots safelyrytm_list_audio_inputsdiscover capture devicesrytm_capture_pattern_audiobounded 48 kHz stereo takerytm_capture_multitrack_audioOverbridge stems, optionalrytm_snapshot_stateraw SysEx checkpointrytm_rollback_snapshotbyte-exact restoreA standard MCP stdio server. Two adapters sit behind the
same 32 tools — start with mock, which answers everything
in-process with no hardware and no daemon.
1 Clone and install
$ git clone https://github.com/chronick/analog-rytm-agent-bridge $ cd analog-rytm-agent-bridge && npm install
2 Attach it to Claude Code
The mock adapter first, then the real device when you are ready.
$ claude mcp add rytm -- npm run mcp $ claude mcp add rytm-hw -- npm run mcp:hardware
3 Or configure any MCP client
Claude Desktop, or anything else that speaks stdio MCP. Use an
absolute path, and set cwd to the checkout so the hardware
adapter can launch the Rust daemon.
{
"mcpServers": {
"rytm": {
"command": "node",
"args": [
"--experimental-transform-types",
"/path/to/analog-rytm-agent-bridge/src/bin/mcp-server.ts",
"--adapter", "hardware",
"--clock-source", "observed"
],
"cwd": "/path/to/analog-rytm-agent-bridge"
}
}
}
“what's on pattern A01?” should make the agent reach for
rytm_inspect_pattern. Full setup, every flag, and
troubleshooting live in
docs/MCP.md.
A refused or failed Rytm operation
comes back as a normal tool result with isError and a
readable reason, not a protocol fault — the agent sees why and adapts
instead of losing the connection.
Patterns, machines, sounds, scenes, performance macros, and samples in one JSON declaration — useful when you want a repeatable starting point rather than a conversation.
$ npm run build:project -- declaration.json --execute --auto-slots
{
"project": "layered-kick-demo",
"sounds": {
"BD": {
"machine": "bdplastic",
"machineParams": { "tun": -14, "swt": 54, "dec": 45, "lev": 110 },
"filter": { "filter_type": "Pk", "resonance": 40 },
"amp": { "overdrive": 8 }
},
"BT": {
"machine": "btclassic",
"lfo": { "destination": "SampleFineTune", "waveform": "Tri", "depth": 32 }
}
}
}
Patterns take a step-grid shorthand too — "X... X... X... X...", where X is an accent, x a normal hit, o a ghost note, and . is silence — so a rhythm can be written the way you'd sketch it on paper.
A declaration with samples is preflighted
against the device's RAM inventory before anything is applied. Each
declared slot must be free or already hold that sample's own content;
otherwise you get a conflict report and a non-zero exit having changed
nothing. --auto-slots remaps conflicts, rewrites the p-locks
and kit fields that pointed at them, and stays idempotent across repeat
runs. Slots the declaration does not own are never touched.
Capture is part of the loop rather than an afterthought, which is what makes an actual iteration possible: program a pattern, play it, record it, analyze the take, adjust, go again.
48 kHz stereo WAV through class-compliant CoreAudio, atomically finalized with an authoritative state sidecar. Silence, clipping, duration mismatch, dropped callback blocks, disconnects, and stale partial files are all detected — a broken recording is reported, not quietly analyzed.
If the Overbridge provider is installed, capture Main, eight physical voice groups, and the external input from one synchronized CoreAudio stream, frame-aligned. Independent of the control plane — plug-in hosting and DAW automation are explicitly not supported.
audition:project plays
every pattern in a declaration from generated clock and captures a
verified take per slot, so the output of a build is audio you can listen
to. audition:solo does the same per track, with an RMS and
peak table, when you need to know which voice is actually causing a
problem.
→ Nothing mutates without
--execute. Every persistent write snapshots the affected
objects as raw SysEx first, then reads the device back and compares —
and if the readback disagrees, the original bytes are restored
automatically, across every object it touched.
That is the whole reason an agent gets to touch the instrument at all. It is hardware-certified against an injected failure, not just unit tested. It does not, however, back up your entire device: save to +Drive and take an external backup before first use. Full detail in the README and HARDWARE_SETUP.md.
"Certified" means run against a connected Analog Rytm MKII on OS 1.72, verified by readback, with the device restored to its exact pre-test state. The dated validation certificates in the repo are those runs.
| Area | Status |
|---|---|
| Patterns, kits, sounds, machines | Certified — inspect, delta, apply, snapshot, rollback |
| Scenes & performance macros | Certified — all 12 of each, declarative locks plus transient control |
| Songs | Certified — rows, chains, repeats, per-position mutes, boundary scheduling |
| Samples | Certified — transfer, content identity, RAM resolution, kit rollback |
| Stereo audio capture | Certified — bounded 48 kHz takes with fault detection |
| Overbridge multitrack capture | Certified — Main, eight voice groups, external in, frame-aligned |
| MCP stdio server | Ships — official SDK, all 32 tools, mock and hardware adapters |
| Overbridge plug-in hosting / DAW automation | not implemented explicitly unsupported |
| Song tempo/length overrides, jumps, loops, activation | not implemented |
macOS only — the daemon depends on CoreMIDI and CoreAudio. The codecs target firmware 1.70 and the certificates are from a 1.72 device; neither is a blanket guarantee for other firmware, so unknown-capability operations are gated rather than guessed at.
The whole control plane runs against a mock Rytm transport — no hardware, no MIDI interface, nothing at risk.
1 Clone and install
The TypeScript side has zero runtime dependencies;
npm install provisions only the dev-time type checker.
Needs macOS, Rust ≥ 1.89, and Node ≥ 22.14.
$ git clone https://github.com/chronick/analog-rytm-agent-bridge $ cd analog-rytm-agent-bridge && npm install
2 Drive the mock device
Walks the full lifecycle — inspect, propose, validate, queue, apply, snapshot, roll back — and prints what each stage decided.
$ npm run demo
3 Point it at the real thing
Work through HARDWARE_SETUP.md first, then confirm the device answers before any write.
$ cd daemon && cargo run -- identity $ cargo run -- serve --adapter hardware --clock-source observed