Read and edit DAW projects as an agent, save native Logic projects, convert projects between DAWs
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Check the connected doseedo account: plan tier, the monthly credit pool (DAW conversions draw it), purchased extra-usage credits, and storage. Read-only — consumes nothing. Use it before a batch of conversions to confirm there is budget.
This tool takes no arguments.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http daw-sessions https://api.doseedo.com/mcp/daw
Check the connected doseedo account: plan tier, the monthly credit pool (DAW conversions draw it), purchased extra-usage credits, and storage. Read-only — consumes nothing. Use it before a batch of conversions to confirm there is budget.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Add an audio file to a session from a public https URL (any audio file online; a bounce's pre-signed stem link works as is). Ingested server-side and returned as a sha256 you then use: place it on a track with attach_audio {track_id, blob_sha256}, or load it into a Quick Sampler with load_quick_sampler_sample {track_id, sample_path: "<the sha>"} — it bakes into the downloaded .logicx, no desktop needed (the drum-pack / sample-swap path). A file on the user's machine needs no upload: attach_audio local_path / load_quick_sampler_sample sample_path keep it local (doseedo_edit_ops_reference).
| Argument | Type | Description |
|---|---|---|
| filename | string | Optional name for the asset. |
| audio_key | string | Instead of audio_url: the key of audio already uploaded to this doseedo account (starts with "ingest/"). |
| audio_url | string | https URL of the audio — any public URL, or a doseedo result URL from a job (pre-signed links work as-is; no key needed). |
| session_id* | string |
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"filename": {
"type": "string",
"description": "Optional name for the asset."
},
"audio_key": {
"type": "string",
"description": "Instead of audio_url: the key of audio already uploaded to this doseedo account (starts with \"ingest/\")."
},
"audio_url": {
"type": "string",
"description": "https URL of the audio — any public URL, or a doseedo result URL from a job (pre-signed links work as-is; no key needed)."
},
"session_id": {
"type": "string"
}
},
"additionalProperties": false
}Bounce a session (or specific tracks) to audio through their REAL plugin chains, offline — Dø Desktop renders them in the background WITHOUT the user opening the DAW (live via Logic if it's open, headless if it isn't; this is the thing stock DAWs can't do). Headless renders AUDIO tracks only — an instrument/MIDI track needs the project open in Logic. A track that could not render is named in the error with its reason. Async: returns a job_id — poll with doseedo_wait_task. The result is downloadable stem URLs. Needs Dø Desktop to run at some point to pick up the job; until then it stays queued. No credits (rendered on the user's machine). Cancel: a bounce still queued never renders (its budget is refunded); one mid-render has its result dropped on arrival.
| Argument | Type | Description |
|---|---|---|
| stems | boolean | true (default) = one file per track; false = a single mixdown. |
| format | string | Output format (default wav). |
| track_ids | array | Tracks to bounce (t_… ids from doseedo_get_session). Omit to bounce the whole session. |
| session_id* | string | |
| tail_seconds | number | Extra seconds for reverb/delay to ring out (default 2). |
| idempotency_key | string | Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one. |
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"stems": {
"type": "boolean",
"description": "true (default) = one file per track; false = a single mixdown."
},
"format": {
"enum": [
"wav",
"aiff"
],
"type": "string",
"description": "Output format (default wav)."
},
"track_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tracks to bounce (t_… ids from doseedo_get_session). Omit to bounce the whole session."
},
"session_id": {
"type": "string"
},
"tail_seconds": {
"type": "number",
"description": "Extra seconds for reverb/delay to ring out (default 2)."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}Cancel a queued or running job. bounce_session: a bounce still queued never renders (its budget is refunded); one mid-render has its result dropped on arrival. convert_project: a running conversion has no stop — it completes, the job ends as canceled and its output is discarded; the credit is refunded only when the conversion itself fails. A job that already finished answers 409 already_terminal.
| Argument | Type | Description |
|---|---|---|
| job_id* | string | The job_id from doseedo_convert_project, doseedo_bounce_session or doseedo_list_jobs. |
{
"type": "object",
"required": [
"job_id"
],
"properties": {
"job_id": {
"type": "string",
"description": "The job_id from doseedo_convert_project, doseedo_bounce_session or doseedo_list_jobs."
}
},
"additionalProperties": false
}Check an async doseedo job once — a DAW conversion (doseedo_convert_project) or a bounce (doseedo_bounce_session). Returns its status and, when finished, the result: pre-signed file links and, for a conversion, its transfer report (report, lossy, summary, warnings). The job_id alone is enough.
| Argument | Type | Description |
|---|---|---|
| kind | string | Which job kind created the task — convert_project or bounce_session, the name the submit reply carried (convert / bounce are accepted aliases). |
| parts | array | Optional, on a finished job: the result rows to return in full, by name (as the result names them) or index. |
| job_id | string | Alternatively the job_id (job_…) from doseedo_convert_project, doseedo_bounce_session or doseedo_list_jobs — replaces task_id + kind. |
| task_id | string | The task_id returned by a submit tool. |
{
"type": "object",
"properties": {
"kind": {
"enum": [
"convert_project",
"bounce_session",
"convert",
"bounce"
],
"type": "string",
"description": "Which job kind created the task — convert_project or bounce_session, the name the submit reply carried (convert / bounce are accepted aliases)."
},
"parts": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
"description": "Optional, on a finished job: the result rows to return in full, by name (as the result names them) or index."
},
"job_id": {
"type": "string",
"description": "Alternatively the job_id (job_…) from doseedo_convert_project, doseedo_bounce_session or doseedo_list_jobs — replaces task_id + kind."
},
"task_id": {
"type": "string",
"description": "The task_id returned by a submit tool."
}
},
"additionalProperties": false
}Finish a MULTIPART project upload started by doseedo_get_project_upload_url: pass every uploaded part's number and ETag (from the PUT response header; quotes optional). Returns the project_key to pass to doseedo_convert_project / doseedo_import_project. All parts except the last must be the same size (what `split -b` produces). abort:true discards the upload instead.
| Argument | Type | Description |
|---|---|---|
| abort | boolean | true = abandon the upload and free its parts (no project_key results). |
| parts | array | [{part_number, etag}] for EVERY part, in order. |
| upload_id* | string | |
| project_key* | string |
{
"type": "object",
"required": [
"project_key",
"upload_id"
],
"properties": {
"abort": {
"type": "boolean",
"description": "true = abandon the upload and free its parts (no project_key results)."
},
"parts": {
"type": "array",
"items": {
"type": "object",
"required": [
"part_number",
"etag"
],
"properties": {
"etag": {
"type": "string"
},
"part_number": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "[{part_number, etag}] for EVERY part, in order."
},
"upload_id": {
"type": "string"
},
"project_key": {
"type": "string"
}
},
"additionalProperties": false
}DAW CONVERTER: a project rebuilt natively in the target: tracks, MIDI, audio clips, tempo and markers arrive editable (Logic/Ableton/Pro Tools/REAPER pairs also automation, buses/sends, plugin state; into FL 3rd-party plugins only). Sources: Logic .logicx, Ableton .als, FL Studio .flp, Pro Tools .ptx, REAPER .rpp, Cubase .cpr, Dorico .dorico/.musicxml, Studio One .song, GarageBand .band (SOURCE only — zip the .band package like a .logicx; a GarageBand 6 project must be re-saved in GarageBand 10), Bitwig = any .dawproject (Bitwig/Studio One/Cubase export it; a native .bwproject is refused — File > Export… > DAWproject in Bitwig). The enum lists the exact pairs. ★ ASYMMETRIC TARGETS (an undocumented native file is never written): TO Cubase, Studio One or Bitwig = ONE .dawproject the app imports, not a .cpr/.song/.bwproject; TO Dorico = MusicXML (.mxl, Dorico's own notation import), not a .dorico. FROM Cubase the .cpr carries tracks, tempo and MIDI parts but not the audio pool (audio tracks arrive empty). FROM Dorico a .dorico carries players and flows but NOT its notes: convert its MusicXML export instead (.musicxml/.mxl accepted under dorico2*). Every result carries a transfer REPORT: `report`, `lossy`, `summary[]` (what changed), `warnings[]` (read before opening) — relay them; silence is never "lossless". Upload first: doseedo_get_project_upload_url + PUT (zip a project FOLDER so its audio travels; a bare project file works too; multipart past ~4 GB). Directions: "<source>2<target>"; "auto2<target>" detects the source; "<daw>2<daw>" rebuilds Logic/Ableton/FL/REAPER/Pro Tools in place (e.g. options.third_party_plugins:"disable"). To EDIT a project use doseedo_import_project; to convert a session the tools built: doseedo_download_session → upload that zip → logic2<target> (not a session_id). Async: job_id → doseedo_wait_task (15 s–2 min; `stage`); `file` is a direct storage link. Cancel: no stop — it completes, the job ends canceled, output discarded; the credit is refunded only when the conversion itself fails.
| Argument | Type | Description |
|---|---|---|
| options | object | Conversion options (all optional). third_party_plugins:"disable" drops third-party AU/VST devices so the export opens clean on a machine without them; stock_plugins:"disable" leaves stock devices unmapped instead of mapping to the nearest target-DAW device; carry_plugin_presets:false strips plugin patches; lossless:true (→Logic) pins the project to the MAX clip sample rate so no clip is downsampled; project_rate (→Logic) pins an exact rate in Hz; silence_empty_sampler:false (→Logic) keeps Logic's audible default Quick Sampler on tracks whose sampler had no sample; source_name = the project's display name for the output file. |
| direction* | string | Source and target as "<source>2<target>" (logic | ableton | fl | protools | reaper | cubase | dorico | studioone | bitwig | garageband | aaf), "auto2<target>" to let the server detect the source, or "<daw>2<daw>" to rebuild in the same format (Logic/Ableton/FL/REAPER/Pro Tools only). cubase2* reads a .cpr and *2cubase writes a .dawproject (Cubase 14+/Nuendo open it natively). dorico2* reads a .dorico, .musicxml or .mxl and *2dorico writes MusicXML (.mxl). studioone2* reads a .song and *2studioone writes a .dawproject (Studio One 6.5+ imports it). bitwig2* reads any .dawproject and *2bitwig writes a .dawproject (Bitwig 5+ imports it). garageband2* reads a zipped .band package (source only — no *2garageband). aaf2* reads an AAF (Pro Tools / Logic / Resolve / Premiere export) — zip the .aaf with its audio files so clips relink by name; audio only, every clip unwarped at its exact time, no *2aaf or aaf2dorico. |
| project_key* | string | R2 key of the uploaded project (from doseedo_get_project_upload_url / POST /api/upload/r2/signed-url; starts with "uploads/"). |
| idempotency_key | string | Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one. |
{
"type": "object",
"required": [
"project_key",
"direction"
],
"properties": {
"options": {
"type": "object",
"properties": {
"lossless": {
"type": "boolean"
},
"source_name": {
"type": "string",
"description": "Display name of the source project, e.g. \"My Song.als\" — names the output."
},
"project_rate": {
"type": "number",
"description": "Hz, ≥ 8000 (ableton2logic only; overrides lossless)."
},
"stock_plugins": {
"enum": [
"map",
"disable"
],
"type": "string"
},
"third_party_plugins": {
"enum": [
"keep",
"disable"
],
"type": "string"
},
"carry_plugin_presets": {
"type": "boolean"
},
"silence_empty_sampler": {
"type": "boolean"
}
},
"description": "Conversion options (all optional). third_party_plugins:\"disable\" drops third-party AU/VST devices so the export opens clean on a machine without them; stock_plugins:\"disable\" leaves stock devices unmapped instead of mapping to the nearest target-DAW device; carry_plugin_presets:false strips plugin patches; lossless:true (→Logic) pins the project to the MAX clip sample rate so no clip is downsampled; project_rate (→Logic) pins an exact rate in Hz; silence_empty_sampler:false (→Logic) keeps Logic's audible default Quick Sampler on tracks whose sampler had no sample; source_name = the project's display name for the output file.",
"additionalProperties": false
},
"direction": {
"enum": [
"logic2ableton",
"ableton2logic",
"fl2logic",
"fl2ableton",
"ableton2fl",
"logic2fl",
"reaper2logic",
"reaper2ableton",
"reaper2fl",
"logic2reaper",
"ableton2reaper",
"fl2reaper",
"protools2logic",
"protools2ableton",
"protools2fl",
"protools2reaper",
"logic2protools",
"ableton2protools",
"fl2protools",
"reaper2protools",
"cubase2logic",
"cubase2ableton",
"cubase2fl",
"cubase2reaper",
"cubase2protools",
"cubase2dorico",
"logic2cubase",
"ableton2cubase",
"fl2cubase",
"reaper2cubase",
"protools2cubase",
"dorico2logic",
"dorico2ableton",
"dorico2fl",
"dorico2reaper",
"dorico2protools",
"dorico2cubase",
"logic2dorico",
"ableton2dorico",
"fl2dorico",
"reaper2dorico",
"protools2dorico",
"garageband2logic",
"garageband2ableton",
"garageband2fl",
"garageband2reaper",
"garageband2protools",
"garageband2cubase",
"garageband2dorico",
"bitwig2logic",
"bitwig2ableton",
"bitwig2fl",
"bitwig2reaper",
"bitwig2protools",
"bitwig2cubase",
"bitwig2dorico",
"logic2bitwig",
"ableton2bitwig",
"fl2bitwig",
"reaper2bitwig",
"protools2bitwig",
"cubase2bitwig",
"dorico2bitwig",
"studioone2logic",
"studioone2ableton",
"studioone2fl",
"studioone2reaper",
"studioone2protools",
"studioone2cubase",
"logic2studioone",
"ableton2studioone",
"fl2studioone",
"reaper2studioone",
"protools2studioone",
"cubase2studioone",
"aaf2logic",
"aaf2ableton",
"aaf2fl",
"aaf2reaper",
"aaf2protools",
"aaf2cubase",
"aaf2studioone",
"aaf2bitwig",
"logic2logic",
"ableton2ableton",
"fl2fl",
"reaper2reaper",
"protools2protools",
"auto2logic",
"auto2ableton",
"auto2fl",
"auto2reaper",
"auto2protools",
"auto2cubase",
"auto2dorico",
"auto2bitwig",
"auto2studioone"
],
"type": "string",
"description": "Source and target as \"<source>2<target>\" (logic | ableton | fl | protools | reaper | cubase | dorico | studioone | bitwig | garageband | aaf), \"auto2<target>\" to let the server detect the source, or \"<daw>2<daw>\" to rebuild in the same format (Logic/Ableton/FL/REAPER/Pro Tools only). cubase2* reads a .cpr and *2cubase writes a .dawproject (Cubase 14+/Nuendo open it natively). dorico2* reads a .dorico, .musicxml or .mxl and *2dorico writes MusicXML (.mxl). studioone2* reads a .song and *2studioone writes a .dawproject (Studio One 6.5+ imports it). bitwig2* reads any .dawproject and *2bitwig writes a .dawproject (Bitwig 5+ imports it). garageband2* reads a zipped .band package (source only — no *2garageband). aaf2* reads an AAF (Pro Tools / Logic / Resolve / Premiere export) — zip the .aaf with its audio files so clips relink by name; audio only, every clip unwarped at its exact time, no *2aaf or aaf2dorico."
},
"project_key": {
"type": "string",
"description": "R2 key of the uploaded project (from doseedo_get_project_upload_url / POST /api/upload/r2/signed-url; starts with \"uploads/\")."
},
"idempotency_key": {
"type": "string",
"description": "Optional. Any unique string for THIS request (e.g. a UUID). Re-sending the same call with the same key after a timeout returns the same job instead of starting a second one."
}
},
"additionalProperties": false
}Create a new, empty DAW session in the account (a blank project you can then populate with doseedo_edit_session). Returns its session_id.
| Argument | Type | Description |
|---|---|---|
| daw | string | Bound DAW (default logic). |
| name* | string | Session name. |
{
"type": "object",
"required": [
"name"
],
"properties": {
"daw": {
"enum": [
"logic",
"ableton"
],
"type": "string",
"description": "Bound DAW (default logic)."
},
"name": {
"type": "string",
"description": "Session name."
}
},
"additionalProperties": false
}Delete DAW sessions in bulk — a SOFT delete (the sessions disappear from the account and every listing; nothing on the user's disk is touched). Select by ids, or by filters (daw_kind, created_before / created_after, name_contains); filters combine with AND. SAFE BY DEFAULT: without confirm:true this is a DRY RUN that deletes nothing and returns {matched, ids}. Always run the dry run first, show the user the count (and names if few), and call again with confirm:true only after they agree. Never delete sessions the user did not ask to remove.
| Argument | Type | Description |
|---|---|---|
| ids | array | Session ids to delete (up to 500), from doseedo_list_sessions. |
| limit | number | Cap on how many sessions one call may match (default and max 1000). |
| confirm | boolean | false/omitted = dry run (nothing deleted). true = actually delete — only after the user saw the dry-run count and agreed. |
| daw_kind | string | Only sessions bound to this DAW, e.g. "logic", "ableton". |
| created_after | string | ISO-8601 date/time: only sessions created after this. |
| name_contains | string | Only sessions whose name contains this text (case-insensitive). |
| created_before | string | ISO-8601 date/time: only sessions created before this. |
{
"type": "object",
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Session ids to delete (up to 500), from doseedo_list_sessions."
},
"limit": {
"type": "number",
"description": "Cap on how many sessions one call may match (default and max 1000)."
},
"confirm": {
"type": "boolean",
"description": "false/omitted = dry run (nothing deleted). true = actually delete — only after the user saw the dry-run count and agreed."
},
"daw_kind": {
"type": "string",
"description": "Only sessions bound to this DAW, e.g. \"logic\", \"ableton\"."
},
"created_after": {
"type": "string",
"description": "ISO-8601 date/time: only sessions created after this."
},
"name_contains": {
"type": "string",
"description": "Only sessions whose name contains this text (case-insensitive)."
},
"created_before": {
"type": "string",
"description": "ISO-8601 date/time: only sessions created before this."
}
},
"additionalProperties": false
}Is Dø Desktop running on the user's Mac, and can it put edits into their Logic project? Reports which sessions it holds, how it applies edits (apply_mode "reopen" = save, back up, close, apply, reopen), whether macOS lets it (logic_control), each session's last apply (reopen_results) and its applied cursor. Use it to know whether an edit will reach the project now or wait for the next session open. When it is NOT connected the result says how the user gets and pairs the app, and what still works without it. Read-only.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Save a session as a native Logic project (.logicx.zip), rebuilt server-side from the session state — no desktop needed. Returns a short-lived NO-AUTH download_url (plain `curl -o ~/Downloads/…`, no header) plus `replay` = what the build put in the file (per track: kind, Quick Sampler sample + sampler {mode, sample_seconds, start/end, plays_beats}, MIDI note count, audio region count; bundled media; deferred ops the offline build could not synthesize) and `warnings` (e.g. a classic-mode sampler whose notes end before its sample; an unknown sample length). Verify from replay/warnings, never by unzipping ProjectData. `place_local_files` (when present) is ACTION-REQUIRED after unzipping — for Quick Sampler samples AND audio regions from local paths: a replay track with audio_source:"place_local_files" or a "NOT bundled" warning means that file is not in the zip until you run those cp commands; then tell the user the project is complete.
| Argument | Type | Description |
|---|---|---|
| daw | string | Target DAW (default logic; only logic is a one-shot native download — for others use doseedo_convert_project). |
| session_id* | string |
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"daw": {
"enum": [
"logic",
"ableton",
"fl",
"reaper"
],
"type": "string",
"description": "Target DAW (default logic; only logic is a one-shot native download — for others use doseedo_convert_project)."
},
"session_id": {
"type": "string"
}
},
"additionalProperties": false
}The catalog of session edit ops doseedo_edit_session accepts, served in views that each fit one answer (never cut mid-JSON). DEFAULT (no args): units, ids, applies, groups, batching/policy, the recipe NAMES and every op as {op, group, applies, summary} — read it ONCE before a build. Then fetch what you need: op:"load_quick_sampler_sample" (or ops:[…]) → those ops in full (args, units, doc; an unknown name gets did_you_mean); section:"recipes" → the full recipes (drum kit from local samples, fix note lengths, one-shots on an audio track, remote sample, submix bus, verify) — copy one instead of discovering op order; section:"ops" → every op in full; "units" / "ids" / "summary" (the get_session field map + workflow + policy + batching) / "all" (fitted, may shorten). Each op says where it lands (applies: live in the open project | next_open | state). Read-only, no key needed.
| Argument | Type | Description |
|---|---|---|
| op | string | One op name, e.g. "set_midi_notes" — returns that op in full. |
| ops | array | Several op names — returns each in full. |
| section | string | Which part of the catalog. Omit for the default overview. |
{
"type": "object",
"properties": {
"op": {
"type": "string",
"description": "One op name, e.g. \"set_midi_notes\" — returns that op in full."
},
"ops": {
"type": "array",
"items": {
"type": "string"
},
"description": "Several op names — returns each in full."
},
"section": {
"enum": [
"summary",
"ops",
"recipes",
"units",
"ids",
"all"
],
"type": "string",
"description": "Which part of the catalog. Omit for the default overview."
}
},
"additionalProperties": false
}Edit a DAW session with a list of ops (regions, MIDI notes, sampler samples, tracks, mixer faders/pans/mutes, plugins, tempo, markers, key, …): ids and current values from doseedo_get_session, op arguments from doseedo_edit_ops_reference. When sync.live_edits is true Dø Desktop puts it into the user's Logic project (it saves, backs up, closes and reopens the project, ~10–20 s — tell the user); otherwise stored and applied at next open. CONTRACT: every op is validated before anything is stored; a rejection carries a code — unknown_op / unknown_plugin (with did_you_mean), unknown_id (with the valid ids), duplicate_id, forbidden_group, read_only_key — and a reason. atomic (default true): one rejection → NOTHING stored, all rejections listed; atomic:false stores the good ops. RETRY: re-send a timed-out call with the SAME batch_key and it dedups (deduped:true); without batch_key a retry duplicates. Ops apply on the desktop one at a time in order, no per-batch undo — verify with doseedo_download_session (replay).
| Argument | Type | Description |
|---|---|---|
| ops* | array | The edits, e.g. [{"op":"set_track_crop","args":{"track_id":"t_…","start_beats":4,"end_beats":124,"prev_start_beats":24}}, {"op":"set_channel_volume","args":{"channel_id":"ch_…","value":0.6}}]. See doseedo_edit_ops_reference. |
| atomic | boolean | Default true: any rejected op means nothing is stored. Set false to store the valid ops and receive the rest as `rejected`. |
| batch_key | string | A stable id for THIS batch (e.g. "drumkit-build-1"). Same batch_key + same ops on a retry = the same client_op_ids = no duplicates. Always pass one for a build you might have to retry. |
| session_id* | string |
{
"type": "object",
"required": [
"session_id",
"ops"
],
"properties": {
"ops": {
"type": "array",
"items": {
"type": "object",
"required": [
"op",
"args"
],
"properties": {
"op": {
"type": "string",
"description": "The op name, e.g. \"set_track_crop\"."
},
"args": {
"type": "object",
"description": "The op arguments (see the ops reference)."
}
},
"additionalProperties": false
},
"description": "The edits, e.g. [{\"op\":\"set_track_crop\",\"args\":{\"track_id\":\"t_…\",\"start_beats\":4,\"end_beats\":124,\"prev_start_beats\":24}}, {\"op\":\"set_channel_volume\",\"args\":{\"channel_id\":\"ch_…\",\"value\":0.6}}]. See doseedo_edit_ops_reference."
},
"atomic": {
"type": "boolean",
"description": "Default true: any rejected op means nothing is stored. Set false to store the valid ops and receive the rest as `rejected`."
},
"batch_key": {
"type": "string",
"description": "A stable id for THIS batch (e.g. \"drumkit-build-1\"). Same batch_key + same ops on a retry = the same client_op_ids = no duplicates. Always pass one for a build you might have to retry."
},
"session_id": {
"type": "string"
}
},
"additionalProperties": false
}Get a presigned upload for a DAW PROJECT file (for doseedo_convert_project / doseedo_import_project). Zip a project FOLDER so its audio travels with it — and a .logicx or GarageBand .band, which are folders (macOS packages). SIZE LIMITS: a single PUT takes up to 5 GB; guest and free accounts convert projects up to 2 GB, paid plans up to 12 GB (a larger one is refused as project_too_large with the cap and an upgrade link). Pass size_bytes: past 4 GB (or with multipart:true) you get a MULTIPART upload instead — a part_size, one presigned part_url per part, and the complete step (doseedo_complete_project_upload); each part is retried on its own, so a dropped connection costs one part, not the upload. Single PUT: `curl -sS -X PUT -H "Content-Type: application/zip" --data-binary @project.zip "<upload_url>"`, then pass project_key on. Multipart: `split -b <part_size_bytes> project.zip part.` then for each piece in order `curl -sS -X PUT --data-binary @part.aa "<part_url>" -D - -o /dev/null | grep -i etag` (keep each ETag), then doseedo_complete_project_upload {project_key, upload_id, parts}. Need more part URLs than one answer holds? Call this again with project_key + upload_id + part_numbers.
| Argument | Type | Description |
|---|---|---|
| filename | string | File name including extension, e.g. "Song Project.zip", "My Song.band.zip", "beat.flp", "song.cpr", "Mix.song", "set.dawproject" or "score.mxl". |
| multipart | boolean | Force a multipart upload regardless of size (resumable per part). |
| upload_id | string | CONTINUATION: the upload_id the first call returned. |
| size_bytes | number | The file's size in bytes (stat it). Decides single PUT vs multipart and sizes the parts. |
| project_key | string | CONTINUATION of a multipart upload: the key the first call returned. |
| content_type | string | MIME type: application/zip for zips (default), application/octet-stream for bare project files. |
| part_numbers | array | CONTINUATION: which part numbers (1-based) to sign now, ≤ 24 per call. |
{
"type": "object",
"properties": {
"filename": {
"type": "string",
"description": "File name including extension, e.g. \"Song Project.zip\", \"My Song.band.zip\", \"beat.flp\", \"song.cpr\", \"Mix.song\", \"set.dawproject\" or \"score.mxl\"."
},
"multipart": {
"type": "boolean",
"description": "Force a multipart upload regardless of size (resumable per part)."
},
"upload_id": {
"type": "string",
"description": "CONTINUATION: the upload_id the first call returned."
},
"size_bytes": {
"type": "number",
"description": "The file's size in bytes (stat it). Decides single PUT vs multipart and sizes the parts."
},
"project_key": {
"type": "string",
"description": "CONTINUATION of a multipart upload: the key the first call returned."
},
"content_type": {
"type": "string",
"description": "MIME type: application/zip for zips (default), application/octet-stream for bare project files."
},
"part_numbers": {
"type": "array",
"items": {
"type": "number"
},
"description": "CONTINUATION: which part numbers (1-based) to sign now, ≤ 24 per call."
}
},
"additionalProperties": false
}Read a DAW session as the arrangement an agent edits against: every track with its wire ids (track_id t_…, mixer strip channel_id ch_…), regions in BOTH beats and seconds with their MIDI notes (i, pitch, velocity, start_beats, duration_beats — i is what edit_midi_notes selects by), mixer (volume with dB, pan, mute), plugins with params[{param_id, name, value}] (set_device_param needs param_id) and sampler {mode, sample_seconds, plays_beats, …}, sends/output as ch_b_… ids, buses, tempo_bpm + tempo_map, time_signature + meter_map, key_signature when known, markers (marker_id, beat ABSOLUTE from bar 1), automation lanes, instrument, counts, length — and `sync` with live_edits:true|false + live_edits_reason (will an edit reach Logic now?). Field-by-field map: doseedo_edit_ops_reference {section:"summary"}. BUDGET (never cut mid-JSON): notes come inline when the selected tracks hold ≤200 notes, else regions carry note_count + notes_omitted:true — pass include_notes:true with tracks:[ids] for a track's notes; include_params:false / include_automation:false drop params / points; a result still too big is paginated by track with `truncated` + `next` (the exact args for the rest). Read-only. Pass the ids straight to doseedo_edit_session.
| Argument | Type | Description |
|---|---|---|
| tracks | array | Only these tracks (track_id t_… or channel_id ch_…; a track name matches too). The rest of the session (tempo, markers, buses, sync) is always included. |
| session_id* | string | From doseedo_list_sessions. |
| include_notes | boolean | Include MIDI notes. Default: true when the selected tracks hold ≤200 notes in all, else false (regions then carry note_count + notes_omitted:true). |
| include_params | boolean | Include plugin params (default true). false keeps param_count only. |
| include_automation | boolean | Include automation lanes with points (default true). false keeps a lane count per track. |
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"tracks": {
"type": "array",
"items": {
"type": "string"
},
"description": "Only these tracks (track_id t_… or channel_id ch_…; a track name matches too). The rest of the session (tempo, markers, buses, sync) is always included."
},
"session_id": {
"type": "string",
"description": "From doseedo_list_sessions."
},
"include_notes": {
"type": "boolean",
"description": "Include MIDI notes. Default: true when the selected tracks hold ≤200 notes in all, else false (regions then carry note_count + notes_omitted:true)."
},
"include_params": {
"type": "boolean",
"description": "Include plugin params (default true). false keeps param_count only."
},
"include_automation": {
"type": "boolean",
"description": "Include automation lanes with points (default true). false keeps a lane count per track."
}
},
"additionalProperties": false
}Open an uploaded DAW project (Logic .logicx.zip, Ableton .als or project zip, FL .flp, REAPER .rpp, Pro Tools .ptx — zip the folder) as an EDITABLE doseedo session: returns a session_id the session tools then work on (doseedo_get_session → doseedo_edit_session → doseedo_download_session as a native Logic project, or convert that download to another DAW with doseedo_convert_project). The session gets the project's tempo (+ tempo map), meter, markers, and every track with its name, mixer level/pan, color and MIDI notes. AUDIO IS NOT CARRIED: the import reads the project, not its media — audio tracks arrive named and positioned (audio.placements lists each clip's file and beats) and audio.next says how to supply the files. Plugins and summing buses are reported, not recreated. Upload first with doseedo_get_project_upload_url; this call parses the project (seconds to minutes for a big one) — if it answers status:"running", call it again with the returned task_id until it hands back session_id.
| Argument | Type | Description |
|---|---|---|
| daw | string | The source DAW, when the filename does not say (optional; detected otherwise). |
| name | string | Session name (default: the project's own name). |
| task_id | string | CONTINUATION: the task_id a previous call returned while the parse was still running. |
| project_key | string | R2 key of the uploaded project (from doseedo_get_project_upload_url; starts with "uploads/"). |
{
"type": "object",
"properties": {
"daw": {
"enum": [
"logic",
"ableton",
"fl",
"reaper",
"protools"
],
"type": "string",
"description": "The source DAW, when the filename does not say (optional; detected otherwise)."
},
"name": {
"type": "string",
"description": "Session name (default: the project's own name)."
},
"task_id": {
"type": "string",
"description": "CONTINUATION: the task_id a previous call returned while the parse was still running."
},
"project_key": {
"type": "string",
"description": "R2 key of the uploaded project (from doseedo_get_project_upload_url; starts with \"uploads/\")."
}
},
"additionalProperties": false
}List the jobs this account submitted, newest first — DAW conversions (convert_project) and bounces (bounce_session) — to find an earlier result, check what is still running, or resume after a lost connection. Each row names its artifacts; doseedo_check_task {job_id} returns the full result with fresh links. Read-only.
| Argument | Type | Description |
|---|---|---|
| kind | string | Only this job kind: convert_project or bounce_session (convert / bounce are accepted aliases). |
| limit | number | How many (1–100, default 20). |
| before | string | Page cursor: the next_cursor of a previous call. |
| status | string | |
| session_id | string | Only jobs whose input names this session (its bounces), filtered within the fetched page. |
{
"type": "object",
"properties": {
"kind": {
"enum": [
"convert_project",
"bounce_session",
"convert",
"bounce"
],
"type": "string",
"description": "Only this job kind: convert_project or bounce_session (convert / bounce are accepted aliases)."
},
"limit": {
"type": "number",
"description": "How many (1–100, default 20)."
},
"before": {
"type": "string",
"description": "Page cursor: the next_cursor of a previous call."
},
"status": {
"enum": [
"queued",
"running",
"succeeded",
"failed",
"canceled"
],
"type": "string"
},
"session_id": {
"type": "string",
"description": "Only jobs whose input names this session (its bounces), filtered within the fetched page."
}
},
"additionalProperties": false
}List the plugins you can insert on a strip with doseedo_edit_session's add_device op. Returns the stock Logic catalog (instruments + effects, always available) and — when Dø Desktop is connected — the actual plugins installed on the user's Mac (stock + third-party). Insert any of them BY NAME: add_device {channel_id, device: {name: "…"}}.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}List the connected account's DAW sessions (most recently updated first) — their ids, names, DAW, and update time. Pages with limit + offset (the response carries total and next_offset); name_contains filters by name. Use a session id with doseedo_get_session and doseedo_edit_session; clean up old ones with doseedo_delete_sessions.
| Argument | Type | Description |
|---|---|---|
| limit | number | How many to return (default 25, max 200). |
| offset | number | How many to skip (default 0) — pass the previous response's next_offset to get the next page. |
| name_contains | string | Only sessions whose name contains this text (case-insensitive). |
{
"type": "object",
"properties": {
"limit": {
"type": "number",
"description": "How many to return (default 25, max 200)."
},
"offset": {
"type": "number",
"description": "How many to skip (default 0) — pass the previous response's next_offset to get the next page."
},
"name_contains": {
"type": "string",
"description": "Only sessions whose name contains this text (case-insensitive)."
}
},
"additionalProperties": false
}Wait for an async doseedo job — a DAW conversion or a bounce — to finish: polls server-side for up to timeout_seconds (5–50; one call can never hold longer than 50 s), then returns the result or the latest status. If it returns still_running:true, call it again — a conversion usually takes 15 s–2 min, a bounce waits until Dø Desktop renders it. A finished job answers with its output, artifacts (pre-signed links) and note.
| Argument | Type | Description |
|---|---|---|
| kind | string | Which job kind created the task — convert_project or bounce_session, the name the submit reply carried (convert / bounce are accepted aliases). |
| job_id | string | Alternatively the job_id (job_…) from doseedo_convert_project, doseedo_bounce_session or doseedo_list_jobs — replaces task_id + kind. |
| task_id | string | The task_id returned by a submit tool. |
| timeout_seconds | number | Max seconds to wait in this call (5–50, default 45). Start with the submit reply's suggested_next_wait. |
{
"type": "object",
"properties": {
"kind": {
"enum": [
"convert_project",
"bounce_session",
"convert",
"bounce"
],
"type": "string",
"description": "Which job kind created the task — convert_project or bounce_session, the name the submit reply carried (convert / bounce are accepted aliases)."
},
"job_id": {
"type": "string",
"description": "Alternatively the job_id (job_…) from doseedo_convert_project, doseedo_bounce_session or doseedo_list_jobs — replaces task_id + kind."
},
"task_id": {
"type": "string",
"description": "The task_id returned by a submit tool."
},
"timeout_seconds": {
"type": "number",
"description": "Max seconds to wait in this call (5–50, default 45). Start with the submit reply's suggested_next_wait."
}
},
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 9, 2026.