Audio to MIDI from an AI agent, over MCP
Published October 2026
Doseedo's transcription and its musical analysis are tools on the MCP server. Connect it and an agent transcribes a recording to notes — pitch, onset, offset, velocity, confidence — with per-instrument models behind one surface, and answers the questions around them: what key is this in, what tempo and meter, where are the downbeats, what are the chords, and is the part I just wrote harmonically sound. The analysis tools are synchronous and cost nothing, which makes them the grid an agent writes against before it renders a part or places notes in a session.
The tools
doseedo_transcribe— audio in (an upload or any https URL, including a separated stem), notes out as JSON. Hints sharpen it:instrument("piano","sax","vocals","bass"),register,familywhen the instrument is unknown,polyphony—solo,poly, orsectionwith arosterof chairs for a horn section ("trumpet,trumpet,trombone,tenor_sax"). Withtempo_bpmthe note times are also returned in beats.want:"f0"returns the continuous pitch contour instead of notes, for glides, vibrato and intonation.doseedo_analyze_song— key, bpm and a per-beat tempo map, meter, downbeats, sections and chords of a recording, in one synchronous call.doseedo_detect_chords— a chord chart with spans in seconds and beats.doseedo_beat_grid— beat and downbeat times, beats per bar, the beat map.doseedo_analyze_midi— the harmony of notes you wrote, before rendering or placing them.
Transcription is an async job — the server's recipe says 15 to 60 seconds, up to two credits and often none — waited on with doseedo_wait_task. The four analysis tools answer in the same call and are free of credits.
Real output, on a real stem
To make this concrete rather than described, here is doseedo_analyze_song run on a solo piano stem from our public jam set, captured 2026-10-15, trimmed to the shape (the full reply carried 421 chords and 25 tempo-map points):
{
"status": "done",
"kind": "analyze_song",
"bpm": 91,
"key": { "name": "C# major", "root": 1, "scale": "major", "confidence": 0.769 },
"meter": "4/4",
"beats_per_bar": 4,
"chords": [
{ "chord": "F#maj7", "start": 21.03, "end": 24.09, "start_beat": 0, "end_beat": 5, "confidence": 0.73 },
{ "chord": "F#m7", "start": 24.09, "end": 24.79, "start_beat": 5, "end_beat": 6, "confidence": 0.83 },
{ "chord": "Bm", "start": 24.79, "end": 25.55, "start_beat": 6, "end_beat": 7, "confidence": 0.70 },
…
],
"tempo_map": [ { "bpm": 90.35, "time": 21.03 }, { "bpm": 85.91, "time": 53.03 }, { "bpm": 90.65, "time": 64.15 }, … ],
"downbeats": [ 22.19, 24.79, 27.52, 30.20, … ],
"sections": [ { "name": "Section A", "position_beats": 0 }, { "name": "Section A", "position_beats": 33.65 }, … ],
"dynamics": { "fade_in_sec": 21.03, "fade_out_start": 219.82 },
"truncated": [ { "path": "chords", "kept": 105, "total": 421 } ],
"next": "The full result is kept: GET https://api.doseedo.com/api/jobs/ with your key."
}
Three things to read off it. The confidence numbers are real — 0.77 on the key, 0.6 to 0.87 per chord — and an agent should treat a 0.6 chord as a draft. The tempo map drifts (86 to 102 bpm across the take) because a solo piano playing rubato has no fixed grid, which is exactly why a part written against this recording should use the map, not the single bpm. And the piece has a long silent intro: fade_in_sec: 21 is why the first chord starts at 21 seconds.
Run on the same stem, doseedo_detect_chords — the beat-tracked chart — heard the opening as Ebm7 at 166.7 bpm (double-time, the same harmony spelled from its relative minor) with a different grid. That disagreement is honest information, not a bug: a dense or rubato recording is the hard case for both tools, and the recipe's own note says to detect chords on a separated harmonic stem of a mix, or on a clean take, for a chart you can trust. The first call to the analysis service in this capture also timed out at 45 seconds after the service had been idle; the error told the agent to wait 30 seconds and retry once, and the retry answered in a few seconds.
What to ask
> What key and tempo is ./ref.wav in, and where do the
sections change?
> Transcribe the sax solo in ./solo.wav — tenor, monophonic —
and show me the notes in beats at the song's tempo.
> Separate ./mix.wav, transcribe the bass stem, and put the
notes on the Bass track of my "Bridge Demo" session.
> Here's the horn section stem: two trumpets, a trombone and
a tenor. Give me each chair's part.
> Check the harmony of this progression I wrote before you
render it.
The third prompt is the point of having this on the MCP: the notes do not stop at a file. The agent writes them into a session track with set_midi_notes (exact notes, played by the DAW's instrument), or renders them as audio with doseedo_render_midi on a modelled instrument, or hands them to a session build. The MIDI stays as given — the server never snaps or corrects notes behind the agent's back.
Notes, not a .mid file — and why
doseedo_transcribe returns notes as structured JSON rather than a Standard MIDI File, because that is what an agent reasons over: it can filter by confidence, quantise to the grid doseedo_beat_grid returned, split a chord into voices, or check the result against doseedo_analyze_midi before anything is committed. Where a file is the goal, the project tools write one: doseedo_separate_stems with include_midi and doseedo_audio_to_session put per-stem MIDI into a native Logic or Ableton project, and the web tool downloads a .mid directly. Audio to sheet music is the notation end of the same pipeline.
Analysis is free and synchronous; transcription is metered lightly (the recipe says up to two credits, none when a CPU model serves it); doseedo_quote prices any of them first. Calls are revocable per client from Settings → API keys.
Transcribe one from your agent
Connect the server, point it at a recording, and ask what key it is in — that one is free.
The Doseedo MCP server →FAQ
Is there an MCP server for audio-to-MIDI transcription?
Yes. The Doseedo MCP server exposes doseedo_transcribe (audio to notes with instrument, register and polyphony hints, including horn sections by chair) alongside doseedo_analyze_song, doseedo_detect_chords, doseedo_beat_grid and doseedo_analyze_midi. It works from Claude, ChatGPT, Cursor, Gemini CLI, Codex and any MCP client.
What does the transcription return?
Notes as JSON — pitch, onset and offset in seconds (and in beats when a tempo is given), velocity and confidence — or, with want:"f0", the continuous pitch contour. To get a .mid, use the web tool, or let separation or a session build write the MIDI into a project.
Can it detect the key, tempo and chords of a song?
Yes — doseedo_analyze_song returns key, bpm with a per-beat tempo map, meter, downbeats, sections and chords in one synchronous call; detect_chords and beat_grid return the chart and the grid on their own. These cost no credits.
Can an agent put the transcribed notes into my DAW?
Yes. It writes them onto a session track with set_midi_notes, renders them as audio with render_midi on a modelled instrument, or lets audio_to_session build the whole project with per-stem MIDI. With Dø Desktop running, notes written to a Logic session appear in the open project.
Does it handle polyphony and sections?
polyphony "poly" transcribes chords; "section" transcribes a horn section by chair, given a roster such as "trumpet,trumpet,trombone,tenor_sax" or register codes. "solo" is a single monophonic line.
The Doseedo MCP server · one URL, every client
- Logic Prolive edits in the open project
- Ableton Livebuild, read, convert .als
- FL Studioread, convert .flp
- Pro Toolsmove .ptx between DAWs
- REAPERread, edit, convert .rpp
- Any AI agentwhat works today
- Claude & Claude Codephone, desktop, terminal
- ChatGPTas a custom MCP server
- Cursormcp.json, one entry
- Gemini CLIgemini mcp add
- OpenAI Codexcodex mcp add
- VS Code Copilotmcp.json, type http
- All 33 toolsthe reference
- Convert projectsten DAW formats, 75 directions
- Separate stemsvocals, drums, bass, more
- Audio to MIDItranscription, chords, key
- Generate musicsongs, parts, covers
- Bounce offlinethrough real plugins
- Swap a drum packaudio stays local