{"ok":true,"site":{"host":"duet-webmcp.vercel.app","url":"https://duet-webmcp.vercel.app/","type":"live","desc":"Compose music together with AI, directly in your browser.","tools":[{"name":"get_project_state","kind":"answer","impl":"imperative","description":"Use this when you need a concise overview of the live Duet project before choosing an edit. Returns tempo, key, mode, chord track, selection and per-track note summaries without flooding context with every note.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_selection","kind":"answer","impl":"imperative","description":"Use this when you need the exact notes and chord context inside the bars currently selected by the person.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"analyze_harmony","kind":"act","impl":"imperative","description":"Use this when you need deterministic harmonic analysis of a selected or explicit bar range. Duet computes chord functions and scale fit with tonal instead of guessing.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"startBar":{"type":"integer","minimum":0,"maximum":15},"endBar":{"type":"integer","minimum":1,"maximum":16}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_selection","kind":"act","impl":"imperative","description":"Use this when you want to visibly focus the person's editor on a track and bar range before reading or changing it. This changes only the shared cursor, not the music.","inputSchema":{"type":"object","properties":{"trackId":{"type":"string","enum":["melody","bass","chords"]},"startBar":{"type":"integer","minimum":0,"maximum":15},"endBar":{"type":"integer","minimum":1,"maximum":16}},"required":["trackId","startBar","endBar"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_chord_progression","kind":"act","impl":"imperative","description":"Use this when the person asks for a chord progression. Replaces consecutive chord slots from startBar, validates every symbol, and creates audible block or arpeggiated chord notes.","inputSchema":{"type":"object","properties":{"startBar":{"type":"integer","minimum":0,"maximum":15},"chords":{"type":"array","minItems":1,"maxItems":16,"items":{"type":"string","minLength":1,"maxLength":16}},"voicing":{"type":"string","enum":["block","arpeggio"]},"mode":{"type":"string","enum":["draft","apply"],"description":"draft (default): show the result as a ghost preview the person accepts or discards on the page; apply: write immediately because the person explicitly asked for that."},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["startBar","chords"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_notes","kind":"act","impl":"imperative","description":"Use this when you know the exact notes to add to melody, bass, or chords. Note names and beat positions are validated and converted to Duet's internal ticks.","inputSchema":{"type":"object","properties":{"trackId":{"type":"string","enum":["melody","bass","chords"]},"notes":{"type":"array","minItems":1,"maxItems":128,"items":{"type":"object","properties":{"pitchName":{"type":"string","minLength":2,"maxLength":8},"startBeat":{"type":"number","minimum":0,"maximum":64},"durationBeats":{"type":"number","minimum":0.0625,"maximum":64},"velocity":{"type":"integer","minimum":1,"maximum":127}},"required":["pitchName","startBeat","durationBeats"],"additionalProperties":false}},"mode":{"type":"string","enum":["draft","apply"],"description":"draft (default): show the result as a ghost preview the person accepts or discards on the page; apply: write immediately because the person explicitly asked for that."},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["trackId","notes"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"transform_selection","kind":"act","impl":"imperative","description":"Use this when the person asks to transpose, change mode, quantize, or humanize the currently selected notes. Mode changes preserve melodic contour with deterministic tonal mapping.","inputSchema":{"type":"object","properties":{"operation":{"type":"string","enum":["transpose","change_mode","quantize","humanize"]},"amount":{"type":"number","minimum":-24,"maximum":60},"targetMode":{"type":"string","enum":["major","minor","dorian","phrygian","lydian","mixolydian","locrian"]},"mode":{"type":"string","enum":["draft","apply"],"description":"draft (default): show the result as a ghost preview the person accepts or discards on the page; apply: write immediately because the person explicitly asked for that."},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["operation"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"generate_line","kind":"act","impl":"imperative","description":"Use this when the person asks Duet to write a bass, counter melody, or pad over existing chords. Generation follows deterministic chord-tone and voice-leading rules.","inputSchema":{"type":"object","properties":{"role":{"type":"string","enum":["bass","counter_melody","pad"]},"startBar":{"type":"integer","minimum":0,"maximum":15},"endBar":{"type":"integer","minimum":1,"maximum":16},"style":{"type":"string","enum":["simple","flowing","syncopated"]},"mode":{"type":"string","enum":["draft","apply"],"description":"draft (default): show the result as a ghost preview the person accepts or discards on the page; apply: write immediately because the person explicitly asked for that."},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["role","startBar","endBar"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_tempo","kind":"act","impl":"imperative","description":"Use this when the person asks to change playback speed. Duet safely clamps the requested tempo to 40–220 BPM and reports the applied value.","inputSchema":{"type":"object","properties":{"bpm":{"type":"number","minimum":-1000,"maximum":1000},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["bpm"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"play","kind":"act","impl":"imperative","description":"Use this when the person asks to listen to the project or a bar range. Starts Duet's existing browser playback; if sound has not been unlocked, returns a clear user-action request.","inputSchema":{"type":"object","properties":{"startBar":{"type":"integer","minimum":0,"maximum":15},"endBar":{"type":"integer","minimum":1,"maximum":16},"loop":{"type":"boolean"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_recent_activity","kind":"answer","impl":"imperative","description":"Use this at the start of a turn to see what the person did on the page since you last looked: recorded takes, notes added or deleted, chords set, selection moves, undo, drafts they accepted or discarded. Lets you react to their playing instead of asking.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"sinceStateVersion":{"type":"integer","minimum":0,"maximum":1000000},"limit":{"type":"integer","minimum":1,"maximum":40}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"suggest_progressions","kind":"act","impl":"imperative","description":"Use this when the person describes a feeling (happy, sad, dreamy, tense, epic, jazzy, calm) instead of chord names. Returns chord progressions realized in the project's key with a one-line reason each, so you can offer choices in plain words or install one with set_chord_progression / propose_variations.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"mood":{"type":"string","enum":["happy","sad","dreamy","tense","epic","jazzy","calm"]},"bars":{"type":"integer","minimum":1,"maximum":16}},"required":["mood"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"propose_variations","kind":"act","impl":"imperative","description":"Use this to let the person choose by ear. Creates 2–3 alternative drafts for the same bars (chords by mood, or bass / pad / counter melody in different styles, or answers to a phrase). Each appears on the page as a lettered option with Listen / Accept / Discard; nothing is written until one is accepted.","inputSchema":{"type":"object","properties":{"kind":{"type":"string","enum":["chords","bass","pad","counter_melody","answer"]},"startBar":{"type":"integer","minimum":0,"maximum":15},"endBar":{"type":"integer","minimum":1,"maximum":16},"count":{"type":"integer","minimum":2,"maximum":3},"moods":{"type":"array","minItems":1,"maxItems":3,"items":{"type":"string","enum":["happy","sad","dreamy","tense","epic","jazzy","calm"]}},"styles":{"type":"array","minItems":1,"maxItems":3,"items":{"type":"string","maxLength":16}},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["kind","startBar","endBar"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"answer_phrase","kind":"act","impl":"imperative","description":"Call and response. Takes the phrase the person just played or selected on the Melody track and writes an answering phrase in the following bars: same rhythm, moved through the key (echo, sequence, invert or contrast), landing on chord tones. Defaults to the last recorded take, then the selection. Returns a draft the person can hear and accept.","inputSchema":{"type":"object","properties":{"sourceStartBar":{"type":"integer","minimum":0,"maximum":15},"sourceEndBar":{"type":"integer","minimum":1,"maximum":16},"targetStartBar":{"type":"integer","minimum":0,"maximum":15},"answerBars":{"type":"integer","minimum":1,"maximum":4},"style":{"type":"string","enum":["echo","sequence","invert","contrast"]},"mode":{"type":"string","enum":["draft","apply"],"description":"draft (default): show the result as a ghost preview the person accepts or discards on the page; apply: write immediately because the person explicitly asked for that."},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"resolve_draft","kind":"act","impl":"imperative","description":"Accept or discard drafts you proposed. Use after the person tells you which option they like; accepting writes it to the song as a normal undoable change and discards only its rival options (same group), so options for other bars or tracks stay available. Without draftId, acts on the option currently previewed on the page.","inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["accept","discard","discard_all"]},"draftId":{"type":"string","maxLength":32}},"required":["action"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_sections","kind":"act","impl":"imperative","description":"Label parts of the song (Intro, Verse, Chorus…) on the bar ruler so you and the person can talk about 'the chorus' instead of bar numbers. Replaces all labels; each starts at a bar and runs until the next.","inputSchema":{"type":"object","properties":{"sections":{"type":"array","minItems":0,"maxItems":8,"items":{"type":"object","properties":{"startBar":{"type":"integer","minimum":0,"maximum":15},"name":{"type":"string","minLength":1,"maxLength":24}},"required":["startBar","name"],"additionalProperties":false}},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["sections"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_instrument","kind":"act","impl":"imperative","description":"Change the sound of a track: piano, epiano, strings, pad, bass or pluck. Cheap and instantly audible; good when the person says 'softer', 'warmer' or 'like strings'.","inputSchema":{"type":"object","properties":{"trackId":{"type":"string","enum":["melody","bass","chords"]},"instrument":{"type":"string","enum":["piano","epiano","strings","pad","bass","pluck"]},"expectedStateVersion":{"type":"integer","minimum":0,"description":"Optional stateVersion you last read; the call is rejected if the person changed the page since."}},"required":["trackId","instrument"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"describe_selection","kind":"answer","impl":"imperative","description":"Use this when the person says something is missing or asks what could be better but cannot say what. Returns a deterministic plain-language diagnosis of the selected bars (or a given range): empty tracks, missing or static chords, a melody that circles or leaps, notes clashing with their chord or outside the key, each with a suggested tool call. Read it, then offer choices.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"startBar":{"type":"integer","minimum":0,"maximum":15},"endBar":{"type":"integer","minimum":1,"maximum":16}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","apiSurface":"spec","toolCount":18}}