analog-rytm-agent-bridge · part of LEMON

rytm-agent-bridge

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

ASKED FOR ON THE DEVICE
every write is read back off the hardware before it counts · orange = asked for · steel = what the device reported

What you can ask for

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

The tool surface

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.

Inspect — compact summaries, not giant payloads

rytm_inspect_device_statethe whole compact picture
rytm_inspect_patterntrigs, locks, lengths
rytm_inspect_kitkit and FX state
rytm_inspect_track_soundmachine and per-page params
rytm_inspect_songrows, chains, repeats, mutes
rytm_inspect_globalrouting, MIDI, sequencer
rytm_inspect_samples+Drive, 127 RAM slots
rytm_describe_capabilitieswhat this firmware supports

Program — proposed, validated, committed

rytm_propose_pattern_deltadescribe a pattern change
rytm_propose_song_deltadescribe a song change
rytm_validate_operationscheck before dispatch
rytm_queue_operationshold for a musical boundary
rytm_apply_operations_nowcommit immediately
rytm_get_eventsacknowledgements, state changes

Play — transient gestures, never persistent

rytm_trigger_trackhit a voice
rytm_set_transportstart, stop, continue
rytm_change_patternswitch on a boundary
rytm_set_live_parametertrack level, mute
rytm_set_active_scenescene on/off
rytm_set_performance_macromacro amount

Sample, record, and undo

rytm_upload_samplecontent-identified, no dupes
rytm_resolve_sample_ramslot assignment with readback
rytm_clear_sample_ramfree slots safely
rytm_list_audio_inputsdiscover capture devices
rytm_capture_pattern_audiobounded 48 kHz stereo take
rytm_capture_multitrack_audioOverbridge stems, optional
rytm_snapshot_stateraw SysEx checkpoint
rytm_rollback_snapshotbyte-exact restore

Wiring it up

A 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"
    }
  }
}
then ask it something

“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.

Or describe a whole project at once

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.

It can hear what it made

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.

STEREO

Bounded takes with fault detection

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.

MULTITRACK

Overbridge stems, optional

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.

Reversible by construction

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.

Honest scope

"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.

AreaStatus
Patterns, kits, sounds, machinesCertified — inspect, delta, apply, snapshot, rollback
Scenes & performance macrosCertified — all 12 of each, declarative locks plus transient control
SongsCertified — rows, chains, repeats, per-position mutes, boundary scheduling
SamplesCertified — transfer, content identity, RAM resolution, kit rollback
Stereo audio captureCertified — bounded 48 kHz takes with fault detection
Overbridge multitrack captureCertified — Main, eight voice groups, external in, frame-aligned
MCP stdio serverShips — official SDK, all 32 tools, mock and hardware adapters
Overbridge plug-in hosting / DAW automationnot implemented explicitly unsupported
Song tempo/length overrides, jumps, loops, activationnot 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.

Try it without a drum machine

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