Skip to content

MCP reference

Every tool an agent can call, what it takes, and whether it changes your project.

Every call that changes the project is exactly one undo step.

Protocol: 2025-06-18

Reading

project_describe

Summarise the open project: tempo, meter, and every channel, pattern, playlist track, mixer insert and automation by name and id.read

Start here. It returns counts and names, and not one note, clip or automation point, so it costs a few hundred tokens whatever the size of the arrangement.

Use the ids it returns to address everything else. Reach for project_read only when you need the contents of something this named.

Takes no arguments.

project_read

Read the whole project document, or one top-level member of it, exactly as a .dew file stores it.read

The document through the same schema that reads and writes the file, so what you get back is what is on disk rather than a summary of it.

This is large: a real arrangement is tens of thousands of tokens of notes. Pass member to take one part - 'channels', 'patterns', 'playlist', 'mixer' - and prefer project_describe when you only need to know what exists.

ArgumentTypeNotes
membertextOne top-level member to return instead of the whole document.

params_list

List every parameter at one address, with its range, its default, whether it can be automated, and what it holds now.read

How to find out what is writable before writing it. An address is a target (project, channel, mixerTrack, master), an id, a group and a slot - the same five fields every parameter operation takes.

Leave group off for the target's own parameters. Set it to 'oscillators', 'amp', 'sample' or 'soundfont' for part of a channel's instrument, or to 'effects' with a slot for one effect. What a channel offers depends on what kind of instrument it carries, which project_describe reports as its source.

ArgumentTypeNotes
targettextrequiredproject, channel, mixerTrack or master.
idintegerThe channel id or mixer track id. Unread by project and master.
grouptextoscillators, amp, sample, soundfont or effects. Omit for the target's own parameters.
slotintegerWhich oscillator or which effect slot, counting from 0.
paramtextrequiredThe parameter's name, as params_list gives it.

params_read

Read the current value of any number of parameters.read

Takes a list of addresses and answers with a value for each. An address that names nothing comes back with found=false rather than failing the batch, so one stale id does not cost you the other forty answers.

ArgumentTypeNotes
entriesarray of objectsrequiredThe addresses to read.
entries[].targettextrequiredproject, channel, mixerTrack or master.
entries[].idintegerThe channel id or mixer track id. Unread by project and master.
entries[].grouptextoscillators, amp, sample, soundfont or effects. Omit for the target's own parameters.
entries[].slotintegerWhich oscillator or which effect slot, counting from 0.
entries[].paramtextrequiredThe parameter's name, as params_list gives it.

presets_list

List the factory presets, for instruments and for effects.read

Filter by kind ('instrument' or 'effect') and by type - the id of an effect or an instrument, as project_describe reports a channel's source. A preset is refused if its type is not the slot's, so filtering first is worth doing.

ArgumentTypeNotes
kindtextinstrument or effect.
typetextAn effect or instrument id, such as reverb.

patterns_read

Read one pattern's notes, optionally for one channel only.read

The piano roll's contents. Ask for one channel when you only mean one - a pattern holds every channel's notes, so the whole of a busy one is a lot of tokens for a question about the bass.

ArgumentTypeNotes
idintegerrequiredThe pattern to read.
channelIdintegerReturn only this channel's notes.

automation_targets_list

List every parameter in this project that a curve can be pointed at.read

Whether a parameter can carry a curve is declared beside the parameter itself, so this is a curated set. A read-pointer discontinuity (a sample's reverse and loop), a soundfont's tuning offsets and a pattern's length are absent from it.

Answers in the same five-field address params_write takes, so a parameter you have just set can be automated without translating anything.

ArgumentTypeNotes
containstextOnly targets whose display name contains this.

automation_read

Read one automation curve's points.read

Points come back exactly as they are stored: a value from 0 to 1, a bend and a segment shape. The mapping onto the parameter's own units happens where the curve is PLAYED, not here, so what this answers is what automation_points_write took.

stale is true when the curve points at something that no longer applies - an effect slot that changed type, an oscillator switched out of wavetable mode. A stale curve is inert rather than misapplied.

ArgumentTypeNotes
idintegerrequiredThe automation to read.

score_read

Read the project's score source, and whether it still compiles.read

A dew project can carry the text of the arrangement language that produced it. Checking is free and writes nothing, so this reports the diagnostics without putting a single note on the undo stack.

Read the dew://guide/score resource for the language itself.

ArgumentTypeNotes
checkflagCompile it to report diagnostics. True if absent.

transport_read

Report whether dew is playing, in which mode, and where it is.read

A read, so it is available to a read-only grant. Use it to tell whether something you started is still going.

Takes no arguments.

render_status

Report whether a render is going, and how far along it is.read

Progress runs 0 to 1 across the whole job, stems included. stage names which stem is being written.

Takes no arguments.

Changing

project_command

Create, open or save the project, or step its undo history.changes the project

Verbs about the document rather than edits to it. 'new' and 'open' replace what is open and may be refused when there are unsaved changes; 'save' writes to the project's own file, or to path if you give one.

'undo' and 'redo' step the same history the user's own Cmd-Z steps. Every operation in this table is exactly one step of it, however many entries its batch carried.

ArgumentTypeNotes
verbtextrequirednew, open, save, undo or redo.
pathtextThe file to open, or to save to. Required by 'open'.

structure_write

Set the project's name, tempo, metre or length in bars.changes the project

The metre is not a tempo. Changing beatsPerBar redefines what a bar IS, so the bar lines move - but nothing you have written moves with them: a clip is stored in STEPS, so every note and every clip stays exactly where it sounded. What does change is the song's LENGTH, which is counted in bars: it is rounded up to cover what was already there, in the same undo step.

beatUnit is notational: it names the metre and labels the snap divisions, and does not change how long anything sounds for.

ArgumentTypeNotes
nametextThe project's title.
tempoBpmnumberBeats per minute.
beatsPerBarintegerThe top of the time signature. Load-bearing: it is the bar.
beatUnitintegerThe bottom of the time signature. Notational only.
barsInSongintegerHow long the arrangement is.

params_write

Set any number of parameters anywhere in the project, as one undo step.changes the project

The one tool for every value in the document: a channel's volume, an oscillator's detune, an envelope's release, a sample's fade, a soundfont's tuning, any parameter of any effect, a mixer fader, the master, the tempo.

Every address is resolved before anything is written, so a batch with a bad entry changes nothing at all rather than half of what it asked for. A value outside a parameter's range is clamped to it; a choice given a name it does not have fails and says which names it has.

The whole call is one undo step, however many entries it carried.

ArgumentTypeNotes
entriesarray of objectsrequiredThe parameters to set, and what to set them to.
entries[].targettextrequiredproject, channel, mixerTrack or master.
entries[].idintegerThe channel id or mixer track id. Unread by project and master.
entries[].grouptextoscillators, amp, sample, soundfont or effects. Omit for the target's own parameters.
entries[].slotintegerWhich oscillator or which effect slot, counting from 0.
entries[].paramtextrequiredThe parameter's name, as params_list gives it.
entries[].valueanyrequiredA number, or the id of a choice, or true/false. params_list says which this parameter takes.

channels_write

Add channels, or change the name, colour, routing or mute of existing ones, as one undo step.changes the project

An upsert: an entry with an id changes that channel, an entry without one adds a channel of kind. A field an entry does not mention is left alone, so changing a name does not blank a colour.

This is the channel as an object in the rack. For the sound it makes, use params_write, which reaches every oscillator, envelope and effect parameter it has.

A project holds 64 channels, which is as many as the engine renders. A batch that would take it past that is refused whole rather than adding the ones that fit.

ArgumentTypeNotes
entriesarray of objectsrequiredThe channels to add or change.
entries[].idintegerAn existing channel to change. Omit to add a new one.
entries[].kindtextsynth, audio or soundfont. Read only when adding.
entries[].nametextWhat the channel is called.
entries[].colourtextA hex colour. Empty means inherit the colour of its position.
entries[].mixerTrackIdintegerThe mixer insert to route into.
entries[].mutedflagWhether the channel is silent.

channels_remove

Remove channels and the notes that belong to them.changes the project

One undo step. A channel's notes live in patterns and become unreachable once it is gone, so they go with it. Refuses the whole batch if any id names nothing, rather than removing the ones it recognised.

ArgumentTypeNotes
idsarray of integerrequiredThe channel ids to remove.

source_write

Point an audio channel at a sample file, or a soundfont channel at a file and a sound inside it.changes the project

Only audio and soundfont channels have a source; a synth channel makes its own sound and this refuses it.

For a soundfont, giving a bank and program with no file chooses a different sound inside the font the channel already has, which is deliberately not the same as re-pointing it: re-pointing reloads the whole font.

A soundfont is referenced and never copied. A sample is gathered into the project's Assets folder when the project is saved.

ArgumentTypeNotes
channelIdintegerrequiredThe channel to point.
filetextThe path to the sample or soundfont. Omit to keep the current file.
sourceSampleRateintegerThe sample's own rate, in Hz.
lengthSamplesintegerHow long the sample is, in samples.
bankintegerSoundfont bank. Drum kits are bank 128.
programintegerSoundfont program within the bank.
presetNametextWhat that sound is called, stored so the channel can name it when the font is missing.

effects_write

Add effects to a channel, mixer insert or the master, or bypass and preset existing ones.changes the project

An entry with a slot changes the effect already there; an entry without one appends an effect of type to the end of the chain. A chain holds 9, and one past that is refused rather than silently dropped - an effect the engine does not render is an effect that appears to have stopped working.

The effect's own parameters are params_write's, addressed with group 'effects' and the same slot. preset here is a shorthand for the whole set of them at once; presets_list says what is available.

ArgumentTypeNotes
entriesarray of objectsrequiredThe effects to add or change.
entries[].targettextrequiredchannel, mixerTrack or master.
entries[].idintegerThe channel or mixer track id.
entries[].slotintegerAn existing slot to change. Omit to append a new effect.
entries[].typetextWhat effect to add. Read only when adding.
entries[].enabledflagFalse bypasses the slot.
entries[].presettextA factory preset's name, applied to this slot.

effects_move

Move one effect to another position in its chain.changes the project

Order is audible: a distortion before a reverb is not a distortion after one. Positions count effects only, so the instrument a channel also carries cannot shift the result.

An effect keeps its own DSP unit across the move - the pool is keyed on the effect's identity rather than its position - so reordering a chain does not cut the reverb tail the slots after it were in the middle of.

ArgumentTypeNotes
targettextrequiredchannel, mixerTrack or master.
idintegerThe channel or mixer track id.
slotintegerrequiredWhich effect to move.
toSlotintegerrequiredWhere it should end up.

effects_remove

Remove effects from chains, as one undo step.changes the project

Slots are resolved before anything is removed, so removing slots 0 and 1 in one call removes the two you meant rather than the first and whatever slid up into its place.

ArgumentTypeNotes
entriesarray of objectsrequiredThe effects to remove.
entries[].targettextrequiredchannel, mixerTrack or master.
entries[].idintegerThe channel id or mixer track id. Unread by master.
entries[].slotintegerrequiredWhich effect in that chain, counting from 0.

mixer_write

Add mixer inserts, or rename and recolour existing ones.changes the project

An upsert, like channels_write: an entry with an id changes that insert, one without adds a new one.

A fader and a pan are parameters rather than fields here: reach them with params_write, target 'mixerTrack'. The master is addressed as target 'master', and carries a fader only.

The mixer holds 32 inserts, which is as many as the engine renders. A batch that would take it past that is refused whole rather than adding the ones that fit.

ArgumentTypeNotes
entriesarray of objectsrequiredThe inserts to add or change.
entries[].idintegerAn existing insert to change. Omit to add one.
entries[].nametextWhat the insert is called.
entries[].colourtextA hex colour. Empty means inherit the colours routed into it.

mixer_remove

Remove mixer inserts, their effects and the routing they leave behind.changes the project

Channels routed into a removed insert are re-pointed at the first remaining one in the same undo step, because a channel that has lost its insert is still a channel with notes in it - unlike a clip that has lost its pattern.

Refuses the last insert and refuses the master. Skipped entries are counted in the answer rather than reported as failures.

ArgumentTypeNotes
idsarray of integerrequiredThe insert ids to remove.

patterns_write

Add, duplicate or rename patterns, as one undo step.changes the project

A pattern holds every channel's notes for its span, which is why a section of an arrangement is one pattern rather than one per instrument.

duplicateOf deep-copies a pattern, notes and all, under a new id - which is what a repeat that will be varied wants. A repeat that is identical wants one pattern and two clips instead.

A pattern's LENGTH is not settable, here or anywhere. It is derived from the notes the pattern holds, rounded up to a whole bar and never less than one. lengthSteps is reported back for reference and is not an argument.

ArgumentTypeNotes
entriesarray of objectsrequiredThe patterns to add or change.
entries[].idintegerAn existing pattern to change. Omit to make a new one.
entries[].duplicateOfintegerCopy this pattern, notes and all, instead of making an empty one.
entries[].nametextWhat the pattern is called.

patterns_remove

Remove patterns and every playlist clip that played them.changes the project

One undo step. A clip pointing at a missing pattern would be dropped by the next engine rebuild anyway, so removing it here keeps the document consistent rather than merely tidy.

Refuses the last pattern: a project with none has nothing to edit and nothing to play. A refusal is counted as skipped rather than failing the batch.

ArgumentTypeNotes
idsarray of integerrequiredThe pattern ids to remove.

notes_write

Write notes into a pattern, as one undo step.changes the project

An upsert on the three fields that identify a note - channel, step and pitch - so sending the same bar twice does not double it.

Time is whole steps. A step is 1/stepsPerBeat of a beat, which project_describe reports; at the default 4 a step is a sixteenth note. There is no fractional step and no tuplet that the grid does not divide.

The pattern's length FOLLOWS its notes and is not set directly: writing a note further in lengthens the pattern, and removing the notes at the end shortens it again. Refuses the whole batch on a bad channel or an out-of-range pitch rather than writing half of it.

For anything longer than a few bars, prefer score_write and score_compile: the language says what the music IS, and this says where every note goes.

ArgumentTypeNotes
patternIdintegerrequiredThe pattern to write into.
notesarray of objectsrequiredThe notes.
notes[].channelIdintegerrequiredWhich channel sounds the note.
notes[].stepintegerrequiredWhen it starts, in steps from the pattern's 0.
notes[].pitchintegerrequiredMIDI note number. 60 is middle C.
notes[].lengthStepsintegerHow long it lasts. One step if absent.
notes[].velocitynumberHow hard it is struck, 0.05 to 1.

notes_remove

Remove notes from a pattern, by list or by range.changes the project

Give notes to remove exactly those. Give none and it removes every note in the channel and step range you describe - with no channel and no range, that is every note in the pattern.

One undo step either way.

ArgumentTypeNotes
patternIdintegerrequiredThe pattern to remove from.
notesarray of objectsExactly these notes.
notes[].channelIdintegerrequiredWhich channel sounds the note.
notes[].stepintegerrequiredWhen it starts, in steps from the pattern's 0.
notes[].pitchintegerrequiredMIDI note number. 60 is middle C.
notes[].lengthStepsintegerHow long it lasts. One step if absent.
notes[].velocitynumberHow hard it is struck, 0.05 to 1.
channelIdintegerLimit a range removal to one channel.
fromStepintegerFirst step of the range, inclusive.
toStepintegerLast step of the range, inclusive.

notes_transform

Quantize or transpose every note on one channel of a pattern.changes the project

Quantizing rounds each note's START to the grid and deliberately leaves lengths alone: quantizing length as well turns an eighth-note line into a legato blur. Two notes that land on the same step and pitch are collapsed into one, keeping the longer - they retrigger one voice at one instant, so the second was never audible.

Transposing clamps the notes as a GROUP, so a chord against the top of the range keeps its intervals rather than compressing. The answer says how many semitones were actually applied, which is zero when the group is already against a limit.

A snap division is named, not numbered. The answer repeats the name it used, so a caller can see it got the division it asked for.

ArgumentTypeNotes
patternIdintegerrequiredThe pattern to transform.
channelIdintegerrequiredWhich channel's notes.
verbtextrequiredquantize or transpose.
snaptextFor quantize, one of: off, thirtysecond, sixteenthTriplet, sixteenth, eighthTriplet, eighth, quarter, half, bar. sixteenth if absent. off is the identity, because a step is already the finest position a note holds; a division this project's grid cannot place is refused rather than quietly doing nothing.
semitonesintegerFor transpose: how far, and which way.

playlist_tracks_write

Add arrangement lanes, or rename, mute and recolour existing ones.changes the project

A lane carries no id: lanes are positional, unlike channels and mixer inserts, so an index is the whole address. An entry with an index changes that lane and one without appends a new one.

A lane is not a channel. Any lane can carry a clip of any pattern, and a pattern holds every channel's notes - so lanes are sections of the song, not instruments.

ArgumentTypeNotes
entriesarray of objectsrequiredThe lanes to add or change.
entries[].indexintegerAn existing lane. Omit to append a new one.
entries[].nametextWhat the lane is called.
entries[].muteflagSilence everything on the lane.
entries[].colourtextA hex colour, or empty to inherit.

playlist_tracks_remove

Remove arrangement lanes and the clips on them.changes the project

One undo step. The clips go with the lane. Automations do NOT - an automation is a reusable definition that can be placed again, unlike the notes a removed channel leaves behind, which nothing can reach.

Removing a lane renumbers the ones after it, so give every index you mean in one call rather than calling repeatedly.

ArgumentTypeNotes
indexesarray of integerrequiredThe lane indexes to remove.

clips_write

Place clips on the arrangement: patterns, audio takes or automation curves.changes the project

A clip is measured in BARS, and a bar is stepsPerBeat * beatsPerBar steps - 16 in a default 4/4 project, which project_describe reports. Placing two clips of one pattern is how a section repeats identically; duplicating the pattern first is how it repeats with variation.

The song grows to fit what you place, and never shrinks: trailing empty bars are a deliberate silence.

Refuses the whole batch rather than placing some of it: on a bad lane, pattern, channel or automation, on a negative start, and on an audio clip aimed at a channel that has no recording to play.

ArgumentTypeNotes
clipsarray of objectsrequiredThe clips to place.
clips[].trackintegerrequiredWhich lane, counting from 0.
clips[].kindtextpattern, audio or automation. Pattern if absent.
clips[].startBarintegerWhere it begins, counting from 0.
clips[].lengthBarsintegerHow many bars it spans.
clips[].startStepintegerWhere it begins, in steps. Overrides startBar, and is the only way to start a clip off a bar line.
clips[].lengthStepsintegerHow many steps it spans. Overrides lengthBars.
clips[].patternIdintegerFor a pattern clip.
clips[].channelIdintegerFor an audio clip.
clips[].automationIdintegerFor an automation clip.

clips_remove

Remove the clip covering a bar on a lane.changes the project

Addressed by where it is rather than by an id, because that is how a clip is identified on screen: a lane and a bar. A bar with no clip on it is skipped rather than failing the batch, so clearing a range is safe to ask for twice.

ArgumentTypeNotes
clipsarray of objectsrequiredLane-and-bar pairs.
clips[].trackintegerrequiredWhich lane.
clips[].atBarintegerAny bar the clip covers.
clips[].atStepintegerAny step the clip covers. Overrides atBar, and is how to reach a clip that does not begin on a bar line.

automation_write

Create an automation curve for a parameter, and place a clip for it.changes the project

Creating the curve and placing its clip is one call because it is one action: a curve with nowhere to play is a curve nothing hears. The clip lands on the first lane with room at startBar, and a lane is added if every one is occupied there.

A fresh curve has two points rather than none, so it is something you can hear before you shape it - a line for a continuous parameter, and a pair of steps for a discrete one, because half-on is not a state a toggle has. Shape it with automation_points_write.

Refuses a parameter that is not automatable, and says so - which is a different answer from a parameter that does not exist.

ArgumentTypeNotes
targettextrequiredproject, channel, mixerTrack or master.
idintegerThe channel or mixer track id.
grouptextoscillators, amp, soundfont or effects. Omit for the target's own parameters.
slotintegerWhich oscillator or effect slot.
paramtextrequiredThe parameter to automate.
placeClipflagPlace a clip for it. True if absent.
startBarintegerWhere the clip begins.
lengthBarsintegerHow many bars it spans.

automation_points_write

Add or move points on an automation curve, as one undo step.changes the project

A point is a step and a value from 0 to 1. Two points on one step is a curve with no defined value there, so a point written where one already sits moves it rather than duplicating it.

Three shapes are offered and two are stored: 'line' is a curve with no bend, so switching to 'step' and back returns the curve you had. A stepped segment ignores its bend rather than losing it.

replace removes whatever was there that you did not write, which is how you redraw a curve rather than add to it. A curve always keeps at least two points - one with fewer has no shape to evaluate - so replacing with a single point leaves one of the old ones behind, and the answer's points count says so.

ArgumentTypeNotes
idintegerrequiredThe automation to shape.
replaceflagClear the existing points first.
pointsarray of objectsrequiredThe points.
points[].stepnumberrequiredWhere, in steps from the clip's start.
points[].valuenumberrequiredWhat, from 0 to 1.
points[].shapetextline, curve or step. Applies to the RIGHT.
points[].bendnumberHow the curve bends, -1 to 1.

automation_remove

Remove automation curves and every clip that played them.changes the project

One undo step. A clip pointing at a removed automation would have nothing to drive, so it goes too.

ArgumentTypeNotes
idsarray of integerrequiredThe automation ids to remove.

score_write

Store score source in the project, without compiling it.changes the project

Storing and compiling are separate on purpose: a compile writes notes, and text that is being worked on should not fill the undo stack with them.

The answer says whether what you stored compiles and why not, so you can fix it before asking for the notes.

ArgumentTypeNotes
sourcetextrequiredThe whole score, as text.
sourceNametextWhat to call it in diagnostics.

score_compile

Compile the score into real patterns, notes and clips, as one undo step.changes the project

The language says what the music IS - key, harmony, rhythm, voicing, counterpoint - and the compiler works out the notes. One call arranges a whole section; notes_write places one note at a time.

The language owns notes, patterns and clips; you own channels, instruments, effects and the mixer. Recompiling is an UPDATE rather than a second copy, and hand edits are kept unless you say otherwise.

Refuses outright if the score has errors, rather than baking half of it. Note that the same source always compiles to the same notes, on any machine.

ArgumentTypeNotes
sourcetextCompile this instead of what is stored, and store it too.
sourceNametextWhat to call it in diagnostics.
discardHandEditsflagOverwrite notes edited by hand since the last compile.

transport_write

Start or pause playback, choose song or pattern mode, and move the playhead or the start marker.changes the project

Not an edit: nothing here touches the document or the undo history. It is what the transport bar does.

Any pending change to the document is applied to the engine first, so playing immediately after writing notes plays the notes you just wrote.

ArgumentTypeNotes
playingflagTrue plays, false pauses - which returns to the start marker.
modetextsong plays the arrangement, pattern loops the current pattern.
playheadStepsnumberMove the playhead, in steps.
startMarkerStepsnumberWhere playback begins and where pausing returns to, in steps. Moves the playhead with it.
rewindflagReturn to the start: the playhead and the marker both.

render_audio

Start rendering the project to an audio file, or to one file per mixer insert.changes the project

Answers as soon as the render STARTS, because a render is seconds to minutes of work. Poll render_status for progress, and do not start a second one while one is going.

The format follows the extension. MP3 needs the lame binary to be installed and reports itself unavailable when it is not.

A stem is a full render with the other inserts muted, so it carries the effects and the routing it has in the mix. That also means stems do not sum back to the mix when the master chain holds a non-linear effect.

ArgumentTypeNotes
pathtextrequiredWhere to write. A file, or the folder to fill when stems is set.
modetextsong renders the arrangement, pattern renders one pattern. Song if absent.
patternIdintegerWhich pattern, in pattern mode.
stemsflagWrite one file per MIXER INSERT instead of one mix. Not one per channel - a new project has twenty inserts and usually fewer channels than that.
secondsnumberRender exactly this long, letting the material loop. 0, or absent, renders it once.

export_midi

Write the project's notes to a MIDI file.changes the project

Synchronous, unlike an audio render: writing MIDI is arithmetic over the notes rather than a pass over every sample.

The metre's beatUnit goes into the file's time signature. Audio channels have no notes to write and are reported as warnings rather than silently dropped.

ArgumentTypeNotes
pathtextrequiredWhere to write the file.
modetextsong renders the arrangement, pattern renders one pattern. Song if absent.
patternIdintegerWhich pattern, in pattern mode.