← WebMCP Directory

Tool tree

tonic.stranica.workers.dev

Health & EducationTools verified
Website
Learn piano fundamentals on your computer keyboard or a MIDI piano, with your own AI agent as the tutor. Built on WebMCP. Nothing you play leaves your browser.
Explore capabilities

    page: Every page

    get_startedAnswer

    Call this first when teaching. Returns a small session brief with the teaching rules and exactly one recommended next tool call, including ready-to-use input.

    View tool JSON
    {
      "name": "get_started",
      "kind": "answer",
      "impl": "imperative",
      "description": "Call this first when teaching. Returns a small session brief with the teaching rules and exactly one recommended next tool call, including ready-to-use input.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_teaching_guideAnswer

    How to teach with this page: nine short rules on order, pacing by score, wording for beginners, songs, free play and saving. Read once per session.

    View tool JSON
    {
      "name": "get_teaching_guide",
      "kind": "answer",
      "impl": "imperative",
      "description": "How to teach with this page: nine short rules on order, pacing by score, wording for beginners, songs, free play and saving. Read once per session.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_app_stateAnswer

    Current UI state: mode, running exercise and progress, latest result, tempo, input instrument and highlighted keys. Use get_started for the first call; use this whenever the page state is unclear.

    View tool JSON
    {
      "name": "get_app_state",
      "kind": "answer",
      "impl": "imperative",
      "description": "Current UI state: mode, running exercise and progress, latest result, tempo, input instrument and highlighted keys. Use get_started for the first call; use this whenever the page state is unclear.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_keyboard_layoutAnswer

    Which computer keys play which notes. The student plays the piano on their typing keyboard: home row A S D F G H J K L ; ' are the white keys, W E T Y U O P the black keys, Z and X shift the octave. Use this to give instructions like "press A for C4".

    View tool JSON
    {
      "name": "get_keyboard_layout",
      "kind": "answer",
      "impl": "imperative",
      "description": "Which computer keys play which notes. The student plays the piano on their typing keyboard: home row A S D F G H J K L ; ' are the white keys, W E T Y U O P the black keys, Z and X shift the octave. Use this to give instructions like \"press A for C4\".",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_input_statusAnswer

    Which instrument the student is playing on: computer keyboard or a connected MIDI keyboard / digital piano, with playable range and polyphony. Adapt exercises to it: keep computer-keyboard drills within the range and to triads; a MIDI piano can do two hands and wide arpeggios.

    View tool JSON
    {
      "name": "get_input_status",
      "kind": "answer",
      "impl": "imperative",
      "description": "Which instrument the student is playing on: computer keyboard or a connected MIDI keyboard / digital piano, with playable range and polyphony. Adapt exercises to it: keep computer-keyboard drills within the range and to triads; a MIDI piano can do two hands and wide arpeggios.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_practice_logAnswer

    Past practice sessions and recent attempts with scores, newest first. Use it to pick up where the student left off and to notice trends.

    View tool JSON
    {
      "name": "get_practice_log",
      "kind": "answer",
      "impl": "imperative",
      "description": "Past practice sessions and recent attempts with scores, newest first. Use it to pick up where the student left off and to notice trends.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "description": "Sessions to return, default 10."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    get_attempt_resultsAnswer

    Full results of an attempt: notes hit and missed, timing offsets in milliseconds with early/late tendency, and per-prompt answers for find_note and ear_training. Defaults to the latest attempt. Call it after the student says they have finished an exercise.

    View tool JSON
    {
      "name": "get_attempt_results",
      "kind": "answer",
      "impl": "imperative",
      "description": "Full results of an attempt: notes hit and missed, timing offsets in milliseconds with early/late tendency, and per-prompt answers for find_note and ear_training. Defaults to the latest attempt. Call it after the student says they have finished an exercise.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "attempt_id": {
            "type": "string",
            "description": "Omit for the latest attempt."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    show_on_keyboardAction

    Light up keys on the on-screen piano with a caption, and optionally sound them. Give notes, a chord symbol, or a scale. Good for "this is C major", "here is a G7 chord", or pointing out a single key.

    View tool JSON
    {
      "name": "show_on_keyboard",
      "kind": "act",
      "impl": "imperative",
      "description": "Light up keys on the on-screen piano with a caption, and optionally sound them. Give notes, a chord symbol, or a scale. Good for \"this is C major\", \"here is a G7 chord\", or pointing out a single key.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Note names like [\"C4\",\"E4\",\"G4\"]."
          },
          "chord": {
            "type": "string",
            "description": "Chord symbol like \"Cmaj7\", \"Am\", \"G7\", \"C/E\"."
          },
          "scale_root": {
            "type": "string",
            "description": "Scale root like \"D4\" (use with scale_mode)."
          },
          "scale_mode": {
            "type": "string",
            "description": "major, minor, blues, ..."
          },
          "caption": {
            "type": "string",
            "description": "Short label shown above the keyboard."
          },
          "play": {
            "type": "boolean",
            "description": "Also sound the notes (chords together, scales in sequence)."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    clear_keyboardAction

    Remove highlights and captions from the on-screen piano and stop any reference playback.

    View tool JSON
    {
      "name": "clear_keyboard",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove highlights and captions from the on-screen piano and stop any reference playback.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    play_referenceAction

    Play something for the student to hear, lighting up keys as it plays: a scale, a chord progression, a melody or a rhythm. Same parameters as start_exercise. Returns right away; playback runs for `duration_seconds`.

    View tool JSON
    {
      "name": "play_reference",
      "kind": "act",
      "impl": "imperative",
      "description": "Play something for the student to hear, lighting up keys as it plays: a scale, a chord progression, a melody or a rhythm. Same parameters as start_exercise. Returns right away; playback runs for `duration_seconds`.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "scale",
              "chords",
              "melody",
              "rhythm",
              "find_note",
              "ear_training",
              "song"
            ],
            "description": "scale, chords, melody and rhythm are timed with a metronome. find_note and ear_training are prompt-by-prompt."
          },
          "name": {
            "type": "string",
            "description": "Short title shown to the student."
          },
          "bpm": {
            "type": "number",
            "description": "Tempo 30–240. Beginners: 50–70."
          },
          "root": {
            "type": "string",
            "description": "scale: root like \"C4\" or \"F#3\". ear_training: reference note (default C4)."
          },
          "mode": {
            "type": "string",
            "description": "scale: major, minor, harmonic_minor, melodic_minor, major_pentatonic, minor_pentatonic, blues, dorian, mixolydian, lydian, phrygian, chromatic."
          },
          "octaves": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "scale: default 1."
          },
          "direction": {
            "type": "string",
            "enum": [
              "up",
              "down",
              "up_down"
            ],
            "description": "scale: default up_down."
          },
          "note_value": {
            "type": "string",
            "enum": [
              "quarter",
              "eighth",
              "half"
            ],
            "description": "scale: beats per note, default quarter."
          },
          "progression": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "chords: chord symbols (C, Am, G7, Fmaj7, C/E) or roman numerals (I, ii, V7, vii°). Numerals need `key`."
          },
          "key": {
            "type": "string",
            "description": "chords: key for roman numerals, e.g. \"G\" or \"A minor\"."
          },
          "beats_per_chord": {
            "type": "number",
            "description": "chords: default 4."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "melody: note names in order. rhythm: the single note to tap (default C4). find_note: exact notes to ask for."
          },
          "rhythm": {
            "type": "array",
            "items": {
              "type": "number"
            },
            "description": "melody / rhythm: beats per note, e.g. [1, 1, 0.5, 0.5, 2]."
          },
          "melody": {
            "type": "string",
            "description": "melody: built-in tune id: ode_to_joy, twinkle, mary."
          },
          "count": {
            "type": "integer",
            "description": "find_note / ear_training: number of prompts, default 5."
          },
          "show_hints": {
            "type": "boolean",
            "description": "find_note: light up the answer key."
          },
          "intervals": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "ear_training: intervals to draw from: m2 M2 m3 M3 P4 TT P5 m6 M6 m7 M7 P8."
          },
          "low": {
            "type": "string",
            "description": "find_note: lowest note to ask for (default C4)."
          },
          "high": {
            "type": "string",
            "description": "find_note: highest note to ask for (default B4)."
          },
          "include_black_keys": {
            "type": "boolean",
            "description": "find_note: also ask for sharps and flats. Default false (white keys only)."
          },
          "song_id": {
            "type": "string",
            "description": "song: id from search_songs, e.g. \"fur_elise\"."
          },
          "section": {
            "type": "string",
            "description": "song: section id from get_song, or \"all\" for the whole piece. Default: first section."
          },
          "hands": {
            "type": "string",
            "enum": [
              "right",
              "left",
              "both"
            ],
            "description": "song: default right. \"both\" only where get_song shows a left-hand part."
          },
          "tempo_percent": {
            "type": "number",
            "minimum": 30,
            "maximum": 150,
            "description": "song: percent of the song tempo. Start learners at 60–70."
          },
          "path_step": {
            "type": "string",
            "description": "Learning-path step id from get_learning_paths. Pass path exercises unchanged so progress is tracked."
          }
        },
        "required": [
          "kind"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    set_metronomeAction

    Set the practice tempo and switch the free-running metronome on or off. Exercises use their own bpm and count in one bar automatically.

    View tool JSON
    {
      "name": "set_metronome",
      "kind": "act",
      "impl": "imperative",
      "description": "Set the practice tempo and switch the free-running metronome on or off. Exercises use their own bpm and count in one bar automatically.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "bpm": {
            "type": "number",
            "description": "30–240"
          },
          "on": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    update_settingsAction

    Toggle the app's sound, the key-letter labels on the on-screen piano, or shift which octave the computer keyboard plays (-2 to 2; 0 means A = C4).

    View tool JSON
    {
      "name": "update_settings",
      "kind": "act",
      "impl": "imperative",
      "description": "Toggle the app's sound, the key-letter labels on the on-screen piano, or shift which octave the computer keyboard plays (-2 to 2; 0 means A = C4).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sound": {
            "type": "boolean"
          },
          "show_key_labels": {
            "type": "boolean"
          },
          "octave_shift": {
            "type": "integer",
            "minimum": -2,
            "maximum": 2
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    start_exerciseAction

    Start an exercise on screen for the student to play on their computer keyboard or MIDI keyboard. Timed kinds (scale, chords, melody, rhythm) count in one bar with clicks, light up each target key in time, and end on their own. Untimed kinds (find_note, ear_training) go prompt by prompt. Returns immediately. When the student says they are done, call get_attempt_results. Keep beginners at 50–70 bpm and within the playable range from get_input_status. For a song from the library use kind "song" with song_id, a section id (or "all"), hands and tempo_percent.

    View tool JSON
    {
      "name": "start_exercise",
      "kind": "act",
      "impl": "imperative",
      "description": "Start an exercise on screen for the student to play on their computer keyboard or MIDI keyboard. Timed kinds (scale, chords, melody, rhythm) count in one bar with clicks, light up each target key in time, and end on their own. Untimed kinds (find_note, ear_training) go prompt by prompt. Returns immediately. When the student says they are done, call get_attempt_results. Keep beginners at 50–70 bpm and within the playable range from get_input_status. For a song from the library use kind \"song\" with song_id, a section id (or \"all\"), hands and tempo_percent.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "scale",
              "chords",
              "melody",
              "rhythm",
              "find_note",
              "ear_training",
              "song"
            ],
            "description": "scale, chords, melody and rhythm are timed with a metronome. find_note and ear_training are prompt-by-prompt."
          },
          "name": {
            "type": "string",
            "description": "Short title shown to the student."
          },
          "bpm": {
            "type": "number",
            "description": "Tempo 30–240. Beginners: 50–70."
          },
          "root": {
            "type": "string",
            "description": "scale: root like \"C4\" or \"F#3\". ear_training: reference note (default C4)."
          },
          "mode": {
            "type": "string",
            "description": "scale: major, minor, harmonic_minor, melodic_minor, major_pentatonic, minor_pentatonic, blues, dorian, mixolydian, lydian, phrygian, chromatic."
          },
          "octaves": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "scale: default 1."
          },
          "direction": {
            "type": "string",
            "enum": [
              "up",
              "down",
              "up_down"
            ],
            "description": "scale: default up_down."
          },
          "note_value": {
            "type": "string",
            "enum": [
              "quarter",
              "eighth",
              "half"
            ],
            "description": "scale: beats per note, default quarter."
          },
          "progression": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "chords: chord symbols (C, Am, G7, Fmaj7, C/E) or roman numerals (I, ii, V7, vii°). Numerals need `key`."
          },
          "key": {
            "type": "string",
            "description": "chords: key for roman numerals, e.g. \"G\" or \"A minor\"."
          },
          "beats_per_chord": {
            "type": "number",
            "description": "chords: default 4."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "melody: note names in order. rhythm: the single note to tap (default C4). find_note: exact notes to ask for."
          },
          "rhythm": {
            "type": "array",
            "items": {
              "type": "number"
            },
            "description": "melody / rhythm: beats per note, e.g. [1, 1, 0.5, 0.5, 2]."
          },
          "melody": {
            "type": "string",
            "description": "melody: built-in tune id: ode_to_joy, twinkle, mary."
          },
          "count": {
            "type": "integer",
            "description": "find_note / ear_training: number of prompts, default 5."
          },
          "show_hints": {
            "type": "boolean",
            "description": "find_note: light up the answer key."
          },
          "intervals": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "ear_training: intervals to draw from: m2 M2 m3 M3 P4 TT P5 m6 M6 m7 M7 P8."
          },
          "low": {
            "type": "string",
            "description": "find_note: lowest note to ask for (default C4)."
          },
          "high": {
            "type": "string",
            "description": "find_note: highest note to ask for (default B4)."
          },
          "include_black_keys": {
            "type": "boolean",
            "description": "find_note: also ask for sharps and flats. Default false (white keys only)."
          },
          "song_id": {
            "type": "string",
            "description": "song: id from search_songs, e.g. \"fur_elise\"."
          },
          "section": {
            "type": "string",
            "description": "song: section id from get_song, or \"all\" for the whole piece. Default: first section."
          },
          "hands": {
            "type": "string",
            "enum": [
              "right",
              "left",
              "both"
            ],
            "description": "song: default right. \"both\" only where get_song shows a left-hand part."
          },
          "tempo_percent": {
            "type": "number",
            "minimum": 30,
            "maximum": 150,
            "description": "song: percent of the song tempo. Start learners at 60–70."
          },
          "path_step": {
            "type": "string",
            "description": "Learning-path step id from get_learning_paths. Pass path exercises unchanged so progress is tracked."
          }
        },
        "required": [
          "kind"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    set_practice_planAction

    Replace the student's practice plan shown in the app. Each item can carry an exercise spec so the student can start it with one click. Shows a confirmation card first.

    View tool JSON
    {
      "name": "set_practice_plan",
      "kind": "act",
      "impl": "imperative",
      "description": "Replace the student's practice plan shown in the app. Each item can carry an exercise spec so the student can start it with one click. Shows a confirmation card first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "e.g. \"This week: C major and first chords\""
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string"
                },
                "detail": {
                  "type": "string",
                  "description": "Why, or what to focus on."
                },
                "exercise": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "enum": [
                        "scale",
                        "chords",
                        "melody",
                        "rhythm",
                        "find_note",
                        "ear_training",
                        "song"
                      ],
                      "description": "scale, chords, melody and rhythm are timed with a metronome. find_note and ear_training are prompt-by-prompt."
                    },
                    "name": {
                      "type": "string",
                      "description": "Short title shown to the student."
                    },
                    "bpm": {
                      "type": "number",
                      "description": "Tempo 30–240. Beginners: 50–70."
                    },
                    "root": {
                      "type": "string",
                      "description": "scale: root like \"C4\" or \"F#3\". ear_training: reference note (default C4)."
                    },
                    "mode": {
                      "type": "string",
                      "description": "scale: major, minor, harmonic_minor, melodic_minor, major_pentatonic, minor_pentatonic, blues, dorian, mixolydian, lydian, phrygian, chromatic."
                    },
                    "octaves": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 3,
                      "description": "scale: default 1."
                    },
                    "direction": {
                      "type": "string",
                      "enum": [
                        "up",
                        "down",
                        "up_down"
                      ],
                      "description": "scale: default up_down."
                    },
                    "note_value": {
                      "type": "string",
                      "enum": [
                        "quarter",
                        "eighth",
                        "half"
                      ],
                      "description": "scale: beats per note, default quarter."
                    },
                    "progression": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "chords: chord symbols (C, Am, G7, Fmaj7, C/E) or roman numerals (I, ii, V7, vii°). Numerals need `key`."
                    },
                    "key": {
                      "type": "string",
                      "description": "chords: key for roman numerals, e.g. \"G\" or \"A minor\"."
                    },
                    "beats_per_chord": {
                      "type": "number",
                      "description": "chords: default 4."
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "melody: note names in order. rhythm: the single note to tap (default C4). find_note: exact notes to ask for."
                    },
                    "rhythm": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      },
                      "description": "melody / rhythm: beats per note, e.g. [1, 1, 0.5, 0.5, 2]."
                    },
                    "melody": {
                      "type": "string",
                      "description": "melody: built-in tune id: ode_to_joy, twinkle, mary."
                    },
                    "count": {
                      "type": "integer",
                      "description": "find_note / ear_training: number of prompts, default 5."
                    },
                    "show_hints": {
                      "type": "boolean",
                      "description": "find_note: light up the answer key."
                    },
                    "intervals": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "ear_training: intervals to draw from: m2 M2 m3 M3 P4 TT P5 m6 M6 m7 M7 P8."
                    },
                    "low": {
                      "type": "string",
                      "description": "find_note: lowest note to ask for (default C4)."
                    },
                    "high": {
                      "type": "string",
                      "description": "find_note: highest note to ask for (default B4)."
                    },
                    "include_black_keys": {
                      "type": "boolean",
                      "description": "find_note: also ask for sharps and flats. Default false (white keys only)."
                    },
                    "song_id": {
                      "type": "string",
                      "description": "song: id from search_songs, e.g. \"fur_elise\"."
                    },
                    "section": {
                      "type": "string",
                      "description": "song: section id from get_song, or \"all\" for the whole piece. Default: first section."
                    },
                    "hands": {
                      "type": "string",
                      "enum": [
                        "right",
                        "left",
                        "both"
                      ],
                      "description": "song: default right. \"both\" only where get_song shows a left-hand part."
                    },
                    "tempo_percent": {
                      "type": "number",
                      "minimum": 30,
                      "maximum": 150,
                      "description": "song: percent of the song tempo. Start learners at 60–70."
                    },
                    "path_step": {
                      "type": "string",
                      "description": "Learning-path step id from get_learning_paths. Pass path exercises unchanged so progress is tracked."
                    }
                  },
                  "required": [
                    "kind"
                  ],
                  "additionalProperties": false
                }
              },
              "required": [
                "title"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "title",
          "items"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    complete_plan_itemAction

    Mark a practice-plan item done (or not done) by its id or exact title.

    View tool JSON
    {
      "name": "complete_plan_item",
      "kind": "act",
      "impl": "imperative",
      "description": "Mark a practice-plan item done (or not done) by its id or exact title.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "item_id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "done": {
            "type": "boolean",
            "description": "Default true."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    log_practice_sessionAction

    Save a practice session to the student's log with a short summary and optional tutor notes. Attaches recent attempts (default: everything since the last logged session). Shows a confirmation card first.

    View tool JSON
    {
      "name": "log_practice_session",
      "kind": "act",
      "impl": "imperative",
      "description": "Save a practice session to the student's log with a short summary and optional tutor notes. Attaches recent attempts (default: everything since the last logged session). Shows a confirmation card first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "summary": {
            "type": "string",
            "description": "One or two sentences: what was practiced and how it went."
          },
          "notes": {
            "type": "string",
            "description": "What to work on next time."
          },
          "attempt_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Specific attempts to attach. Omit to attach everything since the last session."
          }
        },
        "required": [
          "summary"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    sayAction

    Speak one or two short sentences out loud through the page, in the browser voice. Use it for coaching while the student has both hands on the keys and eyes on the keyboard, e.g. "Good. Now a little slower." Keep it under 25 words; the student can also read your chat.

    View tool JSON
    {
      "name": "say",
      "kind": "act",
      "impl": "imperative",
      "description": "Speak one or two short sentences out loud through the page, in the browser voice. Use it for coaching while the student has both hands on the keys and eyes on the keyboard, e.g. \"Good. Now a little slower.\" Keep it under 25 words; the student can also read your chat.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    wait_for_resultAction

    Waits until the running exercise finishes, then returns its full results with coaching, so you never need to poll or ask the student to say "done". Call it right after start_exercise. The cap defaults to the time the drill still needs (max 45 s); if they are still playing when it runs out, it returns their progress and you call it again. With nothing running it returns the latest result.

    View tool JSON
    {
      "name": "wait_for_result",
      "kind": "act",
      "impl": "imperative",
      "description": "Waits until the running exercise finishes, then returns its full results with coaching, so you never need to poll or ask the student to say \"done\". Call it right after start_exercise. The cap defaults to the time the drill still needs (max 45 s); if they are still playing when it runs out, it returns their progress and you call it again. With nothing running it returns the latest result.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timeout_seconds": {
            "type": "number",
            "description": "Default 20, max 45."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    wait_for_notesAction

    Listens for the next thing the student plays outside a drill (a note, a chord, or a short burst) and returns it named, e.g. "C major" or "a perfect 5th". Use it for "play me a C chord" checks and "what is this?" moments. Returns after timeout_seconds (default 15, max 45) with nothing if they did not play.

    View tool JSON
    {
      "name": "wait_for_notes",
      "kind": "act",
      "impl": "imperative",
      "description": "Listens for the next thing the student plays outside a drill (a note, a chord, or a short burst) and returns it named, e.g. \"C major\" or \"a perfect 5th\". Use it for \"play me a C chord\" checks and \"what is this?\" moments. Returns after timeout_seconds (default 15, max 45) with nothing if they did not play.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "timeout_seconds": {
            "type": "number",
            "description": "Default 15, max 45."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    get_recent_notesAnswer

    What the student has been playing freely, outside a drill: the notes held right now and what chord or interval they make, the last notes with timing, and the phrase since the last pause. Use it for "what chord is this?", "was that right?", or to react to improvising. Timing is in milliseconds.

    View tool JSON
    {
      "name": "get_recent_notes",
      "kind": "answer",
      "impl": "imperative",
      "description": "What the student has been playing freely, outside a drill: the notes held right now and what chord or interval they make, the last notes with timing, and the phrase since the last pause. Use it for \"what chord is this?\", \"was that right?\", or to react to improvising. Timing is in milliseconds.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "seconds": {
            "type": "number",
            "description": "How far back to look, default 20, max 90."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    save_recording_as_songAction

    Turn what the student just played freely into a song in their library. Takes the phrase since the last pause (or the last N seconds), snaps it to a beat grid, writes it in Tonic notation and shows a confirmation card. Returns the notation so you can read it back or fix it with add_song. Give bpm if you know the tempo they meant; otherwise it is estimated.

    View tool JSON
    {
      "name": "save_recording_as_song",
      "kind": "act",
      "impl": "imperative",
      "description": "Turn what the student just played freely into a song in their library. Takes the phrase since the last pause (or the last N seconds), snaps it to a beat grid, writes it in Tonic notation and shows a confirmation card. Returns the notation so you can read it back or fix it with add_song. Give bpm if you know the tempo they meant; otherwise it is estimated.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "bpm": {
            "type": "number",
            "description": "Tempo the student was playing at. Estimated if omitted."
          },
          "beats_per_bar": {
            "type": "integer",
            "description": "Default 4."
          },
          "grid": {
            "type": "string",
            "enum": [
              "quarter",
              "eighth",
              "sixteenth"
            ],
            "description": "Smallest note to snap to, default eighth."
          },
          "seconds": {
            "type": "number",
            "description": "Use the last N seconds instead of the phrase since the last pause."
          },
          "key": {
            "type": "string"
          },
          "genre": {
            "type": "string",
            "enum": [
              "kids",
              "folk",
              "holiday",
              "hymn",
              "classical"
            ]
          },
          "moods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "calm",
                "joyful",
                "playful",
                "festive",
                "melancholic",
                "solemn",
                "majestic"
              ]
            }
          }
        },
        "required": [
          "title"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    add_songAction

    Add a song to the student's library so it gets Listen, Practice, sections and progress like any other song. Write the melody in Tonic notation: note names with octave (C4, F#4, Bb3) and beats after a colon (E4:0.5, G4:2; default 1), "-" for a rest ("-:2"), [C3 E3 G3] for a chord, "|" bar lines optional. Every section must be whole bars; an optional left hand (lh) must be the same length as the right hand (rh). Keep right-hand notes within C4–F5 so they fit the computer keyboard. The page validates and shows a confirmation card before saving. Prefer public-domain tunes or the student's own material. Example: {"title":"Ode to Joy","key":"C major","bpm":80,"sections":[{"name":"Theme","rh":"E4 E4 F4 G4 | G4 F4 E4 D4 | C4 C4 D4 E4 | E4:1.5 D4:0.5 D4:2"}]}

    View tool JSON
    {
      "name": "add_song",
      "kind": "act",
      "impl": "imperative",
      "description": "Add a song to the student's library so it gets Listen, Practice, sections and progress like any other song. Write the melody in Tonic notation: note names with octave (C4, F#4, Bb3) and beats after a colon (E4:0.5, G4:2; default 1), \"-\" for a rest (\"-:2\"), [C3 E3 G3] for a chord, \"|\" bar lines optional. Every section must be whole bars; an optional left hand (lh) must be the same length as the right hand (rh). Keep right-hand notes within C4–F5 so they fit the computer keyboard. The page validates and shows a confirmation card before saving. Prefer public-domain tunes or the student's own material. Example: {\"title\":\"Ode to Joy\",\"key\":\"C major\",\"bpm\":80,\"sections\":[{\"name\":\"Theme\",\"rh\":\"E4 E4 F4 G4 | G4 F4 E4 D4 | C4 C4 D4 E4 | E4:1.5 D4:0.5 D4:2\"}]}",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "origin": {
            "type": "string",
            "description": "Composer or tradition and year, e.g. \"Traditional Irish\"."
          },
          "genre": {
            "type": "string",
            "enum": [
              "kids",
              "folk",
              "holiday",
              "hymn",
              "classical"
            ]
          },
          "moods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "calm",
                "joyful",
                "playful",
                "festive",
                "melancholic",
                "solemn",
                "majestic"
              ]
            }
          },
          "difficulty": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "key": {
            "type": "string",
            "description": "e.g. \"F major\" or \"A minor\". Flat keys spell notes with flats."
          },
          "bpm": {
            "type": "number",
            "description": "30–240, default 80."
          },
          "beats_per_bar": {
            "type": "integer",
            "description": "Default 4. Use 3 for waltzes; count 6/8 in eighths with 6."
          },
          "blurb": {
            "type": "string",
            "description": "One line for the student."
          },
          "techniques": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Short id like \"a\", \"verse\". Default a, b, c…"
                },
                "name": {
                  "type": "string",
                  "description": "Shown to the student, e.g. \"Verse\"."
                },
                "rh": {
                  "type": "string",
                  "description": "Right-hand melody in Tonic notation."
                },
                "lh": {
                  "type": "string",
                  "description": "Optional left hand, same length as rh."
                }
              },
              "required": [
                "rh"
              ],
              "additionalProperties": false
            }
          },
          "form": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Section order for the whole song, e.g. [\"a\",\"b\",\"a\"]. Default: sections in order."
          }
        },
        "required": [
          "title",
          "sections"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    remove_songAction

    Remove a song the agent or the student added earlier. Built-in songs cannot be removed. Shows a confirmation card first.

    View tool JSON
    {
      "name": "remove_song",
      "kind": "act",
      "impl": "imperative",
      "description": "Remove a song the agent or the student added earlier. Built-in songs cannot be removed. Shows a confirmation card first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "song_id": {
            "type": "string"
          }
        },
        "required": [
          "song_id"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    show_screenAction

    Move the page to a screen: home (the learning paths), a learning path by id, songs (optionally with a song expanded), or practice (plan and log). Closes a finished result if it is showing. Use this instead of clicking links or menus.

    View tool JSON
    {
      "name": "show_screen",
      "kind": "act",
      "impl": "imperative",
      "description": "Move the page to a screen: home (the learning paths), a learning path by id, songs (optionally with a song expanded), or practice (plan and log). Closes a finished result if it is showing. Use this instead of clicking links or menus.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "screen": {
            "type": "string",
            "enum": [
              "home",
              "path",
              "songs",
              "practice"
            ]
          },
          "path_id": {
            "type": "string",
            "enum": [
              "keys",
              "chords",
              "scales",
              "ear"
            ],
            "description": "For screen \"path\"."
          },
          "song_id": {
            "type": "string",
            "description": "For screen \"songs\": expand this song."
          }
        },
        "required": [
          "screen"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    close_resultAction

    Close the result or "listen" card that is showing and return to the page underneath. Same as the student pressing Done.

    View tool JSON
    {
      "name": "close_result",
      "kind": "act",
      "impl": "imperative",
      "description": "Close the result or \"listen\" card that is showing and return to the page underneath. Same as the student pressing Done.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_practice_planAnswer

    The practice plan shown on the Practice screen: each item with its id, whether it is done, and its exercise spec, which you can pass to start_exercise unchanged.

    View tool JSON
    {
      "name": "get_practice_plan",
      "kind": "answer",
      "impl": "imperative",
      "description": "The practice plan shown on the Practice screen: each item with its id, whether it is done, and its exercise spec, which you can pass to start_exercise unchanged.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    replay_promptAction

    In an ear-training drill, play the prompt again for the student. Same as the "Play it again" button.

    View tool JSON
    {
      "name": "replay_prompt",
      "kind": "act",
      "impl": "imperative",
      "description": "In an ear-training drill, play the prompt again for the student. Same as the \"Play it again\" button.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    play_back_attemptAction

    Play back what the student played in an attempt, at the timing they played it, keys lighting up. Same as the "Hear yours" button. Defaults to the latest attempt.

    View tool JSON
    {
      "name": "play_back_attempt",
      "kind": "act",
      "impl": "imperative",
      "description": "Play back what the student played in an attempt, at the timing they played it, keys lighting up. Same as the \"Hear yours\" button. Defaults to the latest attempt.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "attempt_id": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    connect_midiAction

    Try to connect a MIDI keyboard or digital piano. Browsers only grant MIDI access from a real click, so this may fail; if it does, ask the student to press "Connect a MIDI keyboard" under the piano.

    View tool JSON
    {
      "name": "connect_midi",
      "kind": "act",
      "impl": "imperative",
      "description": "Try to connect a MIDI keyboard or digital piano. Browsers only grant MIDI access from a real click, so this may fail; if it does, ask the student to press \"Connect a MIDI keyboard\" under the piano.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    export_progressAction

    Everything stored in this browser (attempts, plan, log, settings, added songs) as JSON, the same as the Export button. Use it to move progress to another browser with import_progress.

    View tool JSON
    {
      "name": "export_progress",
      "kind": "act",
      "impl": "imperative",
      "description": "Everything stored in this browser (attempts, plan, log, settings, added songs) as JSON, the same as the Export button. Use it to move progress to another browser with import_progress.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    import_progressAction

    Replace what is stored in this browser with a JSON export from export_progress or the Export button. Shows a confirmation card first.

    View tool JSON
    {
      "name": "import_progress",
      "kind": "act",
      "impl": "imperative",
      "description": "Replace what is stored in this browser with a JSON export from export_progress or the Export button. Shows a confirmation card first.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "json": {
            "type": "object",
            "description": "The exported object."
          }
        },
        "required": [
          "json"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    reset_progressAction

    Erase the plan, log, attempts, added songs and settings from this browser. Same as the Reset link. Shows a confirmation card first.

    View tool JSON
    {
      "name": "reset_progress",
      "kind": "act",
      "impl": "imperative",
      "description": "Erase the plan, log, attempts, added songs and settings from this browser. Same as the Reset link. Shows a confirmation card first.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    load_sample_progressAction

    Fill the app with a sample plan and practice log, for trying things out. Same as the "Load sample" link. Shows a confirmation card first.

    View tool JSON
    {
      "name": "load_sample_progress",
      "kind": "act",
      "impl": "imperative",
      "description": "Fill the app with a sample plan and practice log, for trying things out. Same as the \"Load sample\" link. Shows a confirmation card first.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    get_learning_pathsAnswer

    The five learning paths the app is organised around (find your way around the keys, learn chords, scales and rhythm, train your ear, play a song) with their steps, which are done, and the next step's ready-to-use exercise. To start a step, pass its exercise to start_exercise unchanged; it carries path_step so the app ticks it off. For songs use search_songs.

    View tool JSON
    {
      "name": "get_learning_paths",
      "kind": "answer",
      "impl": "imperative",
      "description": "The five learning paths the app is organised around (find your way around the keys, learn chords, scales and rhythm, train your ear, play a song) with their steps, which are done, and the next step's ready-to-use exercise. To start a step, pass its exercise to start_exercise unchanged; it carries path_step so the app ticks it off. For songs use search_songs.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "page": "/"
    }
    search_songsAnswer

    Browse the song library: 20 public-domain pieces (kids, folk, holiday, hymn, classical) rated 1–5. Filter by text, genre, mood, difficulty, hands, and whether it fits the computer keyboard. Set for_student true to rank by the student's level, interests, instrument and progress, with a reason per song. Then call get_song, or start_exercise with kind "song".

    View tool JSON
    {
      "name": "search_songs",
      "kind": "answer",
      "impl": "imperative",
      "description": "Browse the song library: 20 public-domain pieces (kids, folk, holiday, hymn, classical) rated 1–5. Filter by text, genre, mood, difficulty, hands, and whether it fits the computer keyboard. Set for_student true to rank by the student's level, interests, instrument and progress, with a reason per song. Then call get_song, or start_exercise with kind \"song\".",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Free text matched against title, composer, genre, moods and techniques."
          },
          "genre": {
            "type": "string",
            "enum": [
              "kids",
              "folk",
              "holiday",
              "hymn",
              "classical"
            ]
          },
          "mood": {
            "type": "string",
            "enum": [
              "calm",
              "joyful",
              "playful",
              "festive",
              "melancholic",
              "solemn",
              "majestic"
            ]
          },
          "max_difficulty": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "min_difficulty": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "hands": {
            "type": "string",
            "enum": [
              "right",
              "both"
            ],
            "description": "\"both\" returns only songs with a left-hand part."
          },
          "fits_computer_keyboard": {
            "type": "boolean",
            "description": "Only songs with at least one section playable on the computer keyboard."
          },
          "for_student": {
            "type": "boolean",
            "description": "Rank by the student profile, interests, instrument and progress."
          },
          "limit": {
            "type": "integer",
            "description": "Default 10."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }
    get_songAnswer

    Everything about one song: each section with length, note range, whether it fits the computer keyboard (and the octave shift it needs), the student's best score, its distinct notes and computer keys, plus ready-made warm-up drills and a suggested first exercise. Call this before starting a song.

    View tool JSON
    {
      "name": "get_song",
      "kind": "answer",
      "impl": "imperative",
      "description": "Everything about one song: each section with length, note range, whether it fits the computer keyboard (and the octave shift it needs), the student's best score, its distinct notes and computer keys, plus ready-made warm-up drills and a suggested first exercise. Call this before starting a song.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "song_id": {
            "type": "string"
          }
        },
        "required": [
          "song_id"
        ],
        "additionalProperties": false
      },
      "page": "/"
    }
    get_song_progressAnswer

    Best score per section and overall mastery for one song, or for every song the student has tried. A song counts as learned when every section scores 80 or more.

    View tool JSON
    {
      "name": "get_song_progress",
      "kind": "answer",
      "impl": "imperative",
      "description": "Best score per section and overall mastery for one song, or for every song the student has tried. A song counts as learned when every section scores 80 or more.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "song_id": {
            "type": "string",
            "description": "Omit for all songs with progress."
          }
        },
        "additionalProperties": false
      },
      "page": "/"
    }