← WebMCP Directory

Tool tree

generative-learning.vercel.app

Health & EducationTools verified
Website
Learn chess and triangles on a real board. Ask what you want to learn. Your AI agent teaches you there.
Explore capabilities

    page: Chess

    get-board-stateAnswer

    Retrieves the current state of the chess board including piece positions, current turn, total moves, game status, and whether learn mode is on.

    View tool JSON
    {
      "name": "get-board-state",
      "kind": "answer",
      "impl": "imperative",
      "description": "Retrieves the current state of the chess board including piece positions, current turn, total moves, game status, and whether learn mode is on.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    make-moveAction

    Makes a chess move. Provide the move as "from:to" (e.g., "e2:e4"). Castling: "e1:g1", "e1:h1", or "O-O". In learn mode, either side may move. Animates with the hand.

    View tool JSON
    {
      "name": "make-move",
      "kind": "act",
      "impl": "imperative",
      "description": "Makes a chess move. Provide the move as \"from:to\" (e.g., \"e2:e4\"). Castling: \"e1:g1\", \"e1:h1\", or \"O-O\". In learn mode, either side may move. Animates with the hand.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "move": {
            "type": "string",
            "description": "Move in format \"from:to\" (e.g., \"e2:e4\"), or O-O / O-O-O to castle",
            "default": "e2:e4"
          }
        },
        "required": [
          "move"
        ]
      },
      "page": "/chess"
    }
    get-possible-movesAnswer

    Gets all legal moves for a piece. Prefer algebraic square (e.g. "e2"); x/y coordinates also work.

    View tool JSON
    {
      "name": "get-possible-moves",
      "kind": "answer",
      "impl": "imperative",
      "description": "Gets all legal moves for a piece. Prefer algebraic square (e.g. \"e2\"); x/y coordinates also work.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "square": {
            "type": "string",
            "description": "Algebraic square such as e2"
          },
          "position": {
            "type": "object",
            "properties": {
              "x": {
                "type": "number",
                "minimum": 0,
                "maximum": 7,
                "description": "X coordinate (0=a, 7=h)"
              },
              "y": {
                "type": "number",
                "minimum": 0,
                "maximum": 7,
                "description": "Y coordinate (0=rank 1, 7=rank 8)"
              }
            }
          }
        }
      },
      "page": "/chess"
    }
    restart-gameAction

    Restarts the chess game to initial position.

    View tool JSON
    {
      "name": "restart-game",
      "kind": "act",
      "impl": "imperative",
      "description": "Restarts the chess game to initial position.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    promote-pawnAction

    Promotes a pawn to queen, rook, bishop, or knight.

    View tool JSON
    {
      "name": "promote-pawn",
      "kind": "act",
      "impl": "imperative",
      "description": "Promotes a pawn to queen, rook, bishop, or knight.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "pieceType": {
            "type": "string",
            "enum": [
              "queen",
              "rook",
              "bishop",
              "knight"
            ],
            "description": "Piece type to promote to."
          }
        },
        "required": [
          "pieceType"
        ]
      },
      "page": "/chess"
    }
    enter-learn-modeAction

    Switch the app into interactive learning mode, or resume the previous lesson if one was saved by exit-learn-mode. Use before teaching, famous games, piece demos, or quizzes. Disables checkmate so teaching positions can omit kings. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O. After anything the student should see on the board (coach text, a played line, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct squares). Do not jump the live playhead while generating. The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.

    View tool JSON
    {
      "name": "enter-learn-mode",
      "kind": "act",
      "impl": "imperative",
      "description": "Switch the app into interactive learning mode, or resume the previous lesson if one was saved by exit-learn-mode. Use before teaching, famous games, piece demos, or quizzes. Disables checkmate so teaching positions can omit kings. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O. After anything the student should see on the board (coach text, a played line, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct squares). Do not jump the live playhead while generating. The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    exit-learn-modeAction

    Leave learning mode, save the current lesson so it can be resumed, clear coaching overlays, and restore a standard playable game.

    View tool JSON
    {
      "name": "exit-learn-mode",
      "kind": "act",
      "impl": "imperative",
      "description": "Leave learning mode, save the current lesson so it can be resumed, clear coaching overlays, and restore a standard playable game.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    list-lessonsAnswer

    Lists famous games, piece tutorials, and saved catalog lessons. create-lesson type: lesson (Goal then add-lesson-step) or showme (one explanation; the line auto-plays with Pause, Stop, and Replay). Riddle: add-lesson-step type riddle. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.

    View tool JSON
    {
      "name": "list-lessons",
      "kind": "answer",
      "impl": "imperative",
      "description": "Lists famous games, piece tutorials, and saved catalog lessons. create-lesson type: lesson (Goal then add-lesson-step) or showme (one explanation; the line auto-plays with Pause, Stop, and Replay). Riddle: add-lesson-step type riddle. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    set-positionAction

    Set the board from FEN or a list of pieces. Enters learn mode. Example pieces: [{ "square": "d4", "type": "knight", "color": "w" }].

    View tool JSON
    {
      "name": "set-position",
      "kind": "act",
      "impl": "imperative",
      "description": "Set the board from FEN or a list of pieces. Enters learn mode. Example pieces: [{ \"square\": \"d4\", \"type\": \"knight\", \"color\": \"w\" }].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "fen": {
            "type": "string",
            "description": "FEN string, e.g. 8/8/8/8/3N4/8/8/8 w - - 0 1"
          },
          "pieces": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "square": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "color": {
                  "type": "string",
                  "description": "w or b"
                }
              }
            }
          },
          "turn": {
            "type": "string",
            "description": "w or b"
          }
        }
      },
      "page": "/chess"
    }
    create-lessonAction

    Create a new catalog lesson. type lesson (default): stores the Goal and moves the student status to the first panel. Later add-lesson-step writes content only and must not move the slider. type showme: one live screen with one explanation; the planned line auto-plays, and the coach has Pause, Stop, and Replay. Call once per topic. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.

    View tool JSON
    {
      "name": "create-lesson",
      "kind": "act",
      "impl": "imperative",
      "description": "Create a new catalog lesson. type lesson (default): stores the Goal and moves the student status to the first panel. Later add-lesson-step writes content only and must not move the slider. type showme: one live screen with one explanation; the planned line auto-plays, and the coach has Pause, Stop, and Replay. Call once per topic. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "lesson",
              "showme"
            ],
            "description": "lesson = Goal then add-lesson-step. showme = one explanation; the line auto-plays with Pause, Stop, and Replay. Pass this enum; do not infer it by matching chat wording."
          },
          "title": {
            "type": "string",
            "description": "Lesson topic shown for the whole lesson, e.g. \"Italian Opening\" or \"Scholar's Mate\"."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "type lesson: optional intro (long algebraic for any moves, e.g. e2-e4). type showme: the single explanation of the line the student will watch."
          },
          "moves": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required for type showme. Planned line as from:to, e.g. [\"e2:e4\", \"e7:e5\"]. The line auto-plays in this order."
          },
          "fen": {
            "type": "string",
            "description": "Optional starting FEN. type lesson: the Goal position (and later riddles unless they pass their own fen). type showme: where the demo starts. Default is the current board."
          }
        },
        "required": [
          "title"
        ]
      },
      "page": "/chess"
    }
    add-lesson-stepAction

    Add ONE catalog item: a teaching Step or a Riddle. Writes the saved lesson only. Do not move the live playhead or board, and never jump the student to the last step while you are still generating. Fast teaching steps do not play the board; why first, then the move; student taps Play when they reach that slide. type riddle stores the puzzle on this lesson — the student solves it when they open that slide (do not wait here, do not jump there). A one-step lesson or riddle has no recap and no Back/Next. State the task only, never how to solve. Before a riddle, call how_to_offer_a_hint. After two or more teaching steps, the student sees Generating... on Next until you add-lesson-step or set-lesson-recap. Same lesson number. Never create-lesson again for the same topic. Not used for create-lesson type showme. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.

    View tool JSON
    {
      "name": "add-lesson-step",
      "kind": "act",
      "impl": "imperative",
      "description": "Add ONE catalog item: a teaching Step or a Riddle. Writes the saved lesson only. Do not move the live playhead or board, and never jump the student to the last step while you are still generating. Fast teaching steps do not play the board; why first, then the move; student taps Play when they reach that slide. type riddle stores the puzzle on this lesson — the student solves it when they open that slide (do not wait here, do not jump there). A one-step lesson or riddle has no recap and no Back/Next. State the task only, never how to solve. Before a riddle, call how_to_offer_a_hint. After two or more teaching steps, the student sees Generating... on Next until you add-lesson-step or set-lesson-recap. Same lesson number. Never create-lesson again for the same topic. Not used for create-lesson type showme. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lesson": {
            "type": "number",
            "description": "Catalog number from create-lesson."
          },
          "type": {
            "type": "string",
            "enum": [
              "step",
              "riddle"
            ],
            "description": "step = teaching beat (title, why, what). riddle = chess puzzle/חידה: question + correct squares, then wait for a click."
          },
          "title": {
            "type": "string",
            "description": "Beat heading, not the lesson title. For a riddle, a short name."
          },
          "why": {
            "type": "string",
            "description": "Teaching steps: situation and goal before the move. Omit for riddles."
          },
          "what": {
            "type": "string",
            "description": "Teaching steps: concrete move(s) in long algebraic notation such as e2-e4, Ng1-f3. Omit for riddles."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional extra detail for teaching steps. Do not spoil a riddle here."
          },
          "moves": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional from:to for Play buttons on teaching steps, e.g. [\"e2:e4\", \"e7:e5\"]."
          },
          "question": {
            "type": "string",
            "description": "Required for type riddle. Puzzle prompt shown to the student. Task only, no spoiler. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O."
          },
          "correct": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required for type riddle. Acceptable squares such as [\"e5\", \"e4\"]."
          },
          "hint": {
            "type": "string",
            "description": "Optional private nudge for type riddle, used only after they tap Give me a hint in chat. Never put this in question. Not shown on the chess page. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O."
          },
          "quizType": {
            "type": "string",
            "enum": [
              "click-square",
              "click-piece",
              "choose-move"
            ],
            "description": "How the student answers a riddle. Default click-square."
          },
          "fen": {
            "type": "string",
            "description": "Optional board FEN for this beat. For a riddle whose pieces are not the Goal position, pass the puzzle FEN here (set-position is frozen while a catalog lesson is on screen). Catalog only; does not move the live board. Default is the position after the previous teaching step."
          }
        },
        "required": [
          "lesson"
        ]
      },
      "page": "/chess"
    }
    set-lesson-recapAction

    Write or replace the Recap screen after the last teaching step. Catalog only; does not change the live playhead. Skip this for one-step lessons such as a chess exam or riddle. Those have no recap. Recap is not a numbered step. Call this when a multi-step line is complete, or rewrite it after extra add-lesson-step beats. Then how_to_ask_the_user. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O. After anything the student should see on the board (coach text, a played line, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct squares). Do not jump the live playhead while generating. The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.

    View tool JSON
    {
      "name": "set-lesson-recap",
      "kind": "act",
      "impl": "imperative",
      "description": "Write or replace the Recap screen after the last teaching step. Catalog only; does not change the live playhead. Skip this for one-step lessons such as a chess exam or riddle. Those have no recap. Recap is not a numbered step. Call this when a multi-step line is complete, or rewrite it after extra add-lesson-step beats. Then how_to_ask_the_user. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O. After anything the student should see on the board (coach text, a played line, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct squares). Do not jump the live playhead while generating. The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lesson": {
            "type": "number",
            "description": "Catalog lesson number."
          },
          "title": {
            "type": "string",
            "description": "Optional recap heading. Default Recap."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Takeaway after the beats so far. Rewrite freely when the student asked something new."
          },
          "body": {
            "type": "string",
            "description": "Fallback if you cannot send paragraphs."
          }
        },
        "required": [
          "lesson",
          "paragraphs"
        ]
      },
      "page": "/chess"
    }
    set-coachAction

    Update the currently visible coach text only when no catalog lesson is on screen. During create-lesson / add-lesson-step this is ignored so the student is not jumped to a later beat. Prefer add-lesson-step. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.

    View tool JSON
    {
      "name": "set-coach",
      "kind": "act",
      "impl": "imperative",
      "description": "Update the currently visible coach text only when no catalog lesson is on screen. During create-lesson / add-lesson-step this is ignored so the student is not jumped to a later beat. Prefer add-lesson-step. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lesson": {
            "type": "number",
            "description": "Catalog lesson number. Reuse it; do not invent a new lesson per move."
          },
          "title": {
            "type": "string",
            "description": "Beat heading, not the whole lesson topic."
          },
          "what": {
            "type": "string",
            "description": "What happens now. Moves must be long algebraic such as e2-e4, Ng1-f3, never short SAN (e4, Nf3)."
          },
          "why": {
            "type": "string",
            "description": "Why this belongs here."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional extra paragraphs after what/why. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O."
          },
          "body": {
            "type": "string",
            "description": "Fallback only if you cannot send paragraphs. Prefer paragraphs."
          },
          "step": {
            "type": "number",
            "description": "1-based teaching step index. Omit to append."
          },
          "totalSteps": {
            "type": "number"
          }
        },
        "required": [
          "title",
          "lesson"
        ]
      },
      "page": "/chess"
    }
    annotate-boardAction

    Highlight squares and draw arrows on the board. kinds: move, capture, key, wrong, correct. Omit highlights or arrows to leave the current ones in place; pass an empty array to clear that overlay. Square names must be English algebraic (e4, f7).

    View tool JSON
    {
      "name": "annotate-board",
      "kind": "act",
      "impl": "imperative",
      "description": "Highlight squares and draw arrows on the board. kinds: move, capture, key, wrong, correct. Omit highlights or arrows to leave the current ones in place; pass an empty array to clear that overlay. Square names must be English algebraic (e4, f7).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "highlights": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "square": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "move",
                    "capture",
                    "key",
                    "wrong",
                    "correct"
                  ]
                }
              }
            }
          },
          "arrows": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string"
                },
                "to": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "page": "/chess"
    }
    clear-lessonAction

    Clear coach text, highlights, arrows, and any pending quiz. Stays in learn mode.

    View tool JSON
    {
      "name": "clear-lesson",
      "kind": "act",
      "impl": "imperative",
      "description": "Clear coach text, highlights, arrows, and any pending quiz. Stays in learn mode.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    load-gameAction

    Load a curated famous game or a saved user-catalog lesson by id or name (scholars-mate, fools-mate, italian-game, opera-game). Sets the starting position. Then call play-line for famous games.

    View tool JSON
    {
      "name": "load-game",
      "kind": "act",
      "impl": "imperative",
      "description": "Load a curated famous game or a saved user-catalog lesson by id or name (scholars-mate, fools-mate, italian-game, opera-game). Sets the starting position. Then call play-line for famous games.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Catalog id or game name"
          }
        },
        "required": [
          "id"
        ]
      },
      "page": "/chess"
    }
    goto-moveAction

    Jump to a ply in the loaded game (0 = start). Rebuilds the position without animation.

    View tool JSON
    {
      "name": "goto-move",
      "kind": "act",
      "impl": "imperative",
      "description": "Jump to a ply in the loaded game (0 = start). Rebuilds the position without animation.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "ply": {
            "type": "number",
            "description": "Number of half-moves from the start"
          }
        },
        "required": [
          "ply"
        ]
      },
      "page": "/chess"
    }
    play-lineAction

    Play moves on the board with the hand animation. During a catalog lesson this does NOT change the coach text. Use add-lesson-step Play buttons instead. For create-lesson type showme, the line auto-plays; the student uses Pause, Stop, and Replay on the coach (do not call this tool to start that demo). Omit moves to continue a loaded famous game. Then call how_to_ask_the_user.

    View tool JSON
    {
      "name": "play-line",
      "kind": "act",
      "impl": "imperative",
      "description": "Play moves on the board with the hand animation. During a catalog lesson this does NOT change the coach text. Use add-lesson-step Play buttons instead. For create-lesson type showme, the line auto-plays; the student uses Pause, Stop, and Replay on the coach (do not call this tool to start that demo). Omit moves to continue a loaded famous game. Then call how_to_ask_the_user.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "moves": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Moves as from:to, e.g. [\"e2:e4\", \"e7:e5\"]"
          },
          "count": {
            "type": "number",
            "description": "If continuing a loaded game, how many plies to play"
          }
        }
      },
      "page": "/chess"
    }
    demonstrate-pieceAction

    Empty-ish board with one piece, legal-move highlights, and a coach explanation of how that piece moves. Then call how_to_ask_the_user.

    View tool JSON
    {
      "name": "demonstrate-piece",
      "kind": "act",
      "impl": "imperative",
      "description": "Empty-ish board with one piece, legal-move highlights, and a coach explanation of how that piece moves. Then call how_to_ask_the_user.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "piece": {
            "type": "string",
            "description": "pawn, knight, bishop, rook, queen, or king"
          },
          "square": {
            "type": "string",
            "description": "Optional square, e.g. d4"
          },
          "color": {
            "type": "string",
            "description": "w or b"
          }
        },
        "required": [
          "piece"
        ]
      },
      "page": "/chess"
    }
    ask-quizAction

    Prefer add-lesson-step with type riddle so the puzzle is stored on the catalog lesson. Do not jump the live playhead. Use this tool only for a one-off quiz that is not a lesson step. Show a puzzle question in the coach panel, hide teaching spoilers, and start a 30-second timer. Wait for a square click. The question must state the task only, never how to solve it, which tactic to use, or which piece or square to look at. Do not put a hint on the chess page. Before this tool, call how_to_offer_a_hint and render the Give me a hint button in this chat. A correct click shows Correct! in the coach only (do not mark the board). A miss or timeout teaches the correct square on the board and in the coach. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.

    View tool JSON
    {
      "name": "ask-quiz",
      "kind": "act",
      "impl": "imperative",
      "description": "Prefer add-lesson-step with type riddle so the puzzle is stored on the catalog lesson. Do not jump the live playhead. Use this tool only for a one-off quiz that is not a lesson step. Show a puzzle question in the coach panel, hide teaching spoilers, and start a 30-second timer. Wait for a square click. The question must state the task only, never how to solve it, which tactic to use, or which piece or square to look at. Do not put a hint on the chess page. Before this tool, call how_to_offer_a_hint and render the Give me a hint button in this chat. A correct click shows Correct! in the coach only (do not mark the board). A miss or timeout teaches the correct square on the board and in the coach. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string",
            "description": "Puzzle prompt shown to the student. Task only, no spoiler. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O."
          },
          "type": {
            "type": "string",
            "enum": [
              "click-square",
              "click-piece",
              "choose-move"
            ]
          },
          "correct": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Acceptable squares such as [\"e5\", \"e4\"]"
          },
          "hint": {
            "type": "string",
            "description": "Optional private nudge to use only after they tap Give me a hint in chat. Never put this in question. Not shown on the chess page. Squares MUST be English algebraic: files a–h and ranks 1–8 (e4, f7, h5). Never transliterate squares. Words may be any language. Moves MUST use long algebraic notation (LAN) so hover can draw the arrow from the exact piece: e2-e4, e7-e5, Ng1-f3, Nb8-c6, Bf1-c4. Captures: e4xd5, Bf1xc4. Never write short SAN for a move (not 1.e4, not e5, not Nf3, not Bc4, not Qh5). That only highlights the destination, as if the piece is unknown. Bare squares (e4, f7) name a location, not a move. Castling may stay O-O / O-O-O."
          }
        },
        "required": [
          "question",
          "correct"
        ]
      },
      "page": "/chess"
    }
    set-page-backgroundAction

    Saves a custom page background for the currently selected board theme only (Classic or Purple). Switching themes shows that theme’s image, or the default theme background if none was set. WebMCP tool arguments are JSON only. There is no native File transfer, so pass the picture as a data URL or raw base64 in `image`, or an http(s) `url`. If the user attached an image in this chat, encode it as base64/data URL and pass it here. Use clear: true to remove the image for the current theme only.

    View tool JSON
    {
      "name": "set-page-background",
      "kind": "act",
      "impl": "imperative",
      "description": "Saves a custom page background for the currently selected board theme only (Classic or Purple). Switching themes shows that theme’s image, or the default theme background if none was set. WebMCP tool arguments are JSON only. There is no native File transfer, so pass the picture as a data URL or raw base64 in `image`, or an http(s) `url`. If the user attached an image in this chat, encode it as base64/data URL and pass it here. Use clear: true to remove the image for the current theme only.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "image": {
            "type": "string",
            "description": "PNG, JPEG, WebP, GIF, or BMP as a data URL (data:image/png;base64,...) or raw base64. Prefer a data URL."
          },
          "mimeType": {
            "type": "string",
            "description": "Required when image is raw base64. Example: image/png or image/jpeg."
          },
          "url": {
            "type": "string",
            "description": "http(s) URL of an image, used as the page background instead of base64."
          },
          "clear": {
            "type": "boolean",
            "description": "If true, remove the custom background for the current theme only."
          }
        }
      },
      "page": "/chess"
    }
    how_to_offer_a_hintAction

    Returns instructions for offering an opt-in Give me a hint visualization button in this chat. Takes no arguments. Call this instead of how_to_ask_the_user while the student is solving, before add-lesson-step type riddle (or ask-quiz for a one-off). Do not spoil the solution in coach text or in this chat until they tap the button. Follow the returned prompt, then add the riddle step. Do not jump the live playhead while generating.

    View tool JSON
    {
      "name": "how_to_offer_a_hint",
      "kind": "act",
      "impl": "imperative",
      "description": "Returns instructions for offering an opt-in Give me a hint visualization button in this chat. Takes no arguments. Call this instead of how_to_ask_the_user while the student is solving, before add-lesson-step type riddle (or ask-quiz for a one-off). Do not spoil the solution in coach text or in this chat until they tap the button. Follow the returned prompt, then add the riddle step. Do not jump the live playhead while generating.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }
    how_to_ask_the_userAction

    Returns instructions for asking the student in this chat with clickable visualization buttons, not a numbered list and not on the chess page. Takes no arguments. Call this whenever you need them to choose what happens next, then follow the returned prompt exactly and stop. Includes the current board-theme accent and a readable label color. After anything the student should see on the board (coach text, a played line, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct squares). Do not jump the live playhead while generating. The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.

    View tool JSON
    {
      "name": "how_to_ask_the_user",
      "kind": "act",
      "impl": "imperative",
      "description": "Returns instructions for asking the student in this chat with clickable visualization buttons, not a numbered list and not on the chess page. Takes no arguments. Call this whenever you need them to choose what happens next, then follow the returned prompt exactly and stop. Includes the current board-theme accent and a readable label color. After anything the student should see on the board (coach text, a played line, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct squares). Do not jump the live playhead while generating. The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/chess"
    }

    page: Home

    list-pagesAnswer

    Lists this site's pages and learning surfaces. You are on the Generative Learning home page. The sub-navigation includes Chess and Triangles (working apps). Other subjects are coming later. Call this to see where you can go, then open-page with page=chess or page=triangles. Chess tools such as get-board-state and triangle tools such as apply-gan are not available until that page loads.

    View tool JSON
    {
      "name": "list-pages",
      "kind": "answer",
      "impl": "imperative",
      "description": "Lists this site's pages and learning surfaces. You are on the Generative Learning home page. The sub-navigation includes Chess and Triangles (working apps). Other subjects are coming later. Call this to see where you can go, then open-page with page=chess or page=triangles. Chess tools such as get-board-state and triangle tools such as apply-gan are not available until that page loads.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/"
    }
    open-pageAction

    Navigate to another page in this site. Use page=chess to open the chess learning app, or page=triangles to open the geometry app. After that navigation, wait for that page's tools before teaching. Use page=about or page=home to return to this home page.

    View tool JSON
    {
      "name": "open-page",
      "kind": "act",
      "impl": "imperative",
      "description": "Navigate to another page in this site. Use page=chess to open the chess learning app, or page=triangles to open the geometry app. After that navigation, wait for that page's tools before teaching. Use page=about or page=home to return to this home page.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "page": {
            "type": "string",
            "enum": [
              "chess",
              "triangles",
              "about",
              "home"
            ],
            "description": "chess = chess learning app. triangles = triangle geometry app. about or home = this home page."
          }
        },
        "required": [
          "page"
        ]
      },
      "page": "/"
    }

    page: Triangles

    get-figure-stateAnswer

    Retrieves the current triangle figure: points, segments, triangles, circles, marks, and measures.

    View tool JSON
    {
      "name": "get-figure-state",
      "kind": "answer",
      "impl": "imperative",
      "description": "Retrieves the current triangle figure: points, segments, triangles, circles, marks, and measures.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/triangles"
    }
    apply-ganAction

    Execute one GAN construction on the triangle figure and animate it with the cursor. Examples: △ABC, h(C,AB), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Semicolons run a sequence. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"].

    View tool JSON
    {
      "name": "apply-gan",
      "kind": "act",
      "impl": "imperative",
      "description": "Execute one GAN construction on the triangle figure and animate it with the cursor. Examples: △ABC, h(C,AB), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Semicolons run a sequence. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "gan": {
            "type": "string",
            "description": "GAN command, e.g. \"h(C,AB)\" or \"△ABC; mark(90,C)\""
          }
        },
        "required": [
          "gan"
        ]
      },
      "page": "/triangles"
    }
    set-figureAction

    Load a triangle figure from a template (scalene, two-triangles, right-at-C, isosceles-AB=AC, 30-60-90, equilateral, ssa-ambiguous) or a TFN string. If a Goal is open with no steps yet, this figure is stored on the lesson and restored later.

    View tool JSON
    {
      "name": "set-figure",
      "kind": "act",
      "impl": "imperative",
      "description": "Load a triangle figure from a template (scalene, two-triangles, right-at-C, isosceles-AB=AC, 30-60-90, equilateral, ssa-ambiguous) or a TFN string. If a Goal is open with no steps yet, this figure is stored on the lesson and restored later.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "template": {
            "type": "string",
            "description": "Named template, e.g. right-at-C"
          },
          "tfn": {
            "type": "string",
            "description": "TFN snapshot from serialize, e.g. A(0,0) B(4,0) C(0,3) △ABC"
          }
        }
      },
      "page": "/triangles"
    }
    move-pointAction

    Move a free point on the triangle figure and animate the cursor to the new location. Constrained points follow.

    View tool JSON
    {
      "name": "move-point",
      "kind": "act",
      "impl": "imperative",
      "description": "Move a free point on the triangle figure and animate the cursor to the new location. Constrained points follow.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "point": {
            "type": "string",
            "description": "Point name, e.g. C"
          },
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          }
        },
        "required": [
          "point",
          "x",
          "y"
        ]
      },
      "page": "/triangles"
    }
    rotate-figureAction

    Rotate named points or a triangle about a point by degrees (CCW positive) and animate it. Example: around A, deg 90, target △ABC.

    View tool JSON
    {
      "name": "rotate-figure",
      "kind": "act",
      "impl": "imperative",
      "description": "Rotate named points or a triangle about a point by degrees (CCW positive) and animate it. Example: around A, deg 90, target △ABC.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "around": {
            "type": "string"
          },
          "deg": {
            "type": "number"
          },
          "target": {
            "type": "string",
            "description": "△ABC or ABC or a point name"
          }
        },
        "required": [
          "around",
          "deg"
        ]
      },
      "page": "/triangles"
    }
    mark-figureAction

    Mark the figure with GAN: mark(90,C), mark(=,AB,AC), mark(∠,BAC,EDF), mark(||,MN,BC), lab(AB=5), highlight(H).

    View tool JSON
    {
      "name": "mark-figure",
      "kind": "act",
      "impl": "imperative",
      "description": "Mark the figure with GAN: mark(90,C), mark(=,AB,AC), mark(∠,BAC,EDF), mark(||,MN,BC), lab(AB=5), highlight(H).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "gan": {
            "type": "string"
          }
        },
        "required": [
          "gan"
        ]
      },
      "page": "/triangles"
    }
    measure-figureAnswer

    Read a measure without drawing: AB, ∠A, △ABC, R, AB:DE.

    View tool JSON
    {
      "name": "measure-figure",
      "kind": "answer",
      "impl": "imperative",
      "description": "Read a measure without drawing: AB, ∠A, △ABC, R, AB:DE.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "GAN object to measure"
          }
        },
        "required": [
          "id"
        ]
      },
      "page": "/triangles"
    }
    list-lessonsAnswer

    Lists saved triangle catalog lessons and figure templates. create-lesson then add-lesson-step. Riddle: add-lesson-step type riddle. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"].

    View tool JSON
    {
      "name": "list-lessons",
      "kind": "answer",
      "impl": "imperative",
      "description": "Lists saved triangle catalog lessons and figure templates. create-lesson then add-lesson-step. Riddle: add-lesson-step type riddle. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"].",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/triangles"
    }
    create-lessonAction

    Create a new triangle catalog lesson. Stores the Goal and moves the student status to the first panel. Later add-lesson-step writes catalog content only and must not move the slider. If the Goal names triangles such as △ABC and △DEF, they are placed on the canvas. GAN tokens stay Latin (△ABC, h(C,AB)). Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"].

    View tool JSON
    {
      "name": "create-lesson",
      "kind": "act",
      "impl": "imperative",
      "description": "Create a new triangle catalog lesson. Stores the Goal and moves the student status to the first panel. Later add-lesson-step writes catalog content only and must not move the slider. If the Goal names triangles such as △ABC and △DEF, they are placed on the canvas. GAN tokens stay Latin (△ABC, h(C,AB)). Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Lesson topic, e.g. \"Altitude to the hypotenuse\"."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional intro. Use GAN for any figure objects."
          }
        },
        "required": [
          "title"
        ]
      },
      "page": "/triangles"
    }
    add-lesson-stepAction

    Add ONE catalog item: a teaching Step or a Riddle. Writes the saved lesson only. Do not change the live figure or jump the student to the last step while you are still generating. Fast teaching steps: why first, then the construction; student taps Play when they reach that slide. type riddle stores the puzzle. The student solves it when they open that slide (do not wait here, do not jump there). A one-step lesson or riddle has no recap and no Back/Next. State the task only, never how to solve. Before a riddle, call how_to_offer_a_hint. After two or more teaching steps, the student sees Generating... on Next until you add-lesson-step or set-lesson-recap. Same lesson number. Never create-lesson again for the same topic. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"].

    View tool JSON
    {
      "name": "add-lesson-step",
      "kind": "act",
      "impl": "imperative",
      "description": "Add ONE catalog item: a teaching Step or a Riddle. Writes the saved lesson only. Do not change the live figure or jump the student to the last step while you are still generating. Fast teaching steps: why first, then the construction; student taps Play when they reach that slide. type riddle stores the puzzle. The student solves it when they open that slide (do not wait here, do not jump there). A one-step lesson or riddle has no recap and no Back/Next. State the task only, never how to solve. Before a riddle, call how_to_offer_a_hint. After two or more teaching steps, the student sees Generating... on Next until you add-lesson-step or set-lesson-recap. Same lesson number. Never create-lesson again for the same topic. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lesson": {
            "type": "number",
            "description": "Catalog number from create-lesson."
          },
          "type": {
            "type": "string",
            "enum": [
              "step",
              "riddle"
            ],
            "description": "step = teaching beat (title, why, what). riddle = puzzle: question + correct GAN objects."
          },
          "title": {
            "type": "string",
            "description": "Beat heading, not the lesson title."
          },
          "why": {
            "type": "string",
            "description": "Teaching steps: situation and goal before the construction. Omit for riddles."
          },
          "what": {
            "type": "string",
            "description": "Teaching steps: GAN construction such as h(C,AB). Omit for riddles."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional extra detail for teaching steps. Do not spoil a riddle here."
          },
          "moves": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional GAN commands for Play buttons, e.g. [\"h(C,AB)\"]."
          },
          "question": {
            "type": "string",
            "description": "Required for type riddle. Puzzle prompt. Task only, no spoiler. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"]."
          },
          "correct": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required for type riddle. Acceptable GAN objects such as [\"H\", \"G\", \"∠C\"]. G is the centroid of △ABC even if that intersection is unlabeled."
          },
          "hint": {
            "type": "string",
            "description": "Optional private nudge for type riddle, used only after they tap Give me a hint in chat. Never put this in question. Not shown on the triangle page. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"]."
          },
          "quizType": {
            "type": "string",
            "enum": [
              "click-square",
              "click-piece",
              "choose-move"
            ],
            "description": "How the student answers a riddle. Default click-square (click a figure object)."
          },
          "tfn": {
            "type": "string",
            "description": "Optional figure TFN for this beat. For a riddle whose figure is not the Goal, pass the puzzle TFN here. Catalog only; does not change the live figure. Default is the figure after the previous teaching step."
          }
        },
        "required": [
          "lesson"
        ]
      },
      "page": "/triangles"
    }
    set-lesson-recapAction

    Write or replace the Recap screen after the last teaching step. Skip this for one-step lessons or a riddle. Those have no recap. Then how_to_ask_the_user. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"]. After anything the student should see on the figure (coach text, a construction, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct GAN objects such as G or ∠C). The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.

    View tool JSON
    {
      "name": "set-lesson-recap",
      "kind": "act",
      "impl": "imperative",
      "description": "Write or replace the Recap screen after the last teaching step. Skip this for one-step lessons or a riddle. Those have no recap. Then how_to_ask_the_user. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"]. After anything the student should see on the figure (coach text, a construction, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct GAN objects such as G or ∠C). The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lesson": {
            "type": "number",
            "description": "Catalog lesson number."
          },
          "title": {
            "type": "string",
            "description": "Optional recap heading. Default Recap."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Takeaway after the beats so far."
          },
          "body": {
            "type": "string",
            "description": "Fallback if you cannot send paragraphs."
          }
        },
        "required": [
          "lesson",
          "paragraphs"
        ]
      },
      "page": "/triangles"
    }
    set-coachAction

    Update the currently visible coach text only when no catalog lesson is on screen. During create-lesson / add-lesson-step this is ignored so the student slider does not jump. Prefer add-lesson-step. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"].

    View tool JSON
    {
      "name": "set-coach",
      "kind": "act",
      "impl": "imperative",
      "description": "Update the currently visible coach text only when no catalog lesson is on screen. During create-lesson / add-lesson-step this is ignored so the student slider does not jump. Prefer add-lesson-step. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lesson": {
            "type": "number",
            "description": "Catalog lesson number."
          },
          "title": {
            "type": "string",
            "description": "Beat heading, not the whole lesson topic."
          },
          "what": {
            "type": "string",
            "description": "What happens now. Constructions must be GAN such as h(C,AB)."
          },
          "why": {
            "type": "string",
            "description": "Why this belongs here."
          },
          "paragraphs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional extra paragraphs after what/why. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"]."
          },
          "body": {
            "type": "string",
            "description": "Fallback only if you cannot send paragraphs."
          },
          "step": {
            "type": "number",
            "description": "1-based teaching step index. Omit to append."
          },
          "totalSteps": {
            "type": "number"
          }
        },
        "required": [
          "title",
          "lesson"
        ]
      },
      "page": "/triangles"
    }
    clear-lessonAction

    Clear coach text, highlights, and any pending quiz.

    View tool JSON
    {
      "name": "clear-lesson",
      "kind": "act",
      "impl": "imperative",
      "description": "Clear coach text, highlights, and any pending quiz.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/triangles"
    }
    ask-quizAction

    Prefer add-lesson-step with type riddle so the puzzle is stored on the catalog lesson. Use this tool only for a one-off quiz that is not a lesson step. Show a puzzle question in the coach panel and start a 30-second timer. Wait for a figure click. The question must state the task only. Before this tool, call how_to_offer_a_hint. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to ["G"].

    View tool JSON
    {
      "name": "ask-quiz",
      "kind": "act",
      "impl": "imperative",
      "description": "Prefer add-lesson-step with type riddle so the puzzle is stored on the catalog lesson. Use this tool only for a one-off quiz that is not a lesson step. Show a puzzle question in the coach panel and start a 30-second timer. Wait for a figure click. The question must state the task only. Before this tool, call how_to_offer_a_hint. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string",
            "description": "Puzzle prompt shown to the student. Task only, no spoiler. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"]."
          },
          "type": {
            "type": "string",
            "enum": [
              "click-square",
              "click-piece",
              "choose-move"
            ]
          },
          "correct": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Acceptable GAN objects such as [\"H\", \"G\", \"∠C\"]"
          },
          "hint": {
            "type": "string",
            "description": "Optional private nudge to use only after they tap Give me a hint in chat. Never put this in question. Not shown on the triangle page. Figure objects and constructions MUST use Latin GAN only: △ABC, ∠A, AB, h(A,BC), m(A,BC), g(△ABC), b(A), circ(ABC), inc(ABC), mid(BC), mark(90,C), fit(△ABC ≅ △DEF), rot(A,90,△ABC), move(C,1,2). Words may be in any language, but the token itself must stay Latin so it can link, highlight, and Play. The centroid of △ABC is G; draw medians with m(A,BC) then label it with g(△ABC), or let the student click the unlabeled intersection and set correct to [\"G\"]."
          }
        },
        "required": [
          "question",
          "correct"
        ]
      },
      "page": "/triangles"
    }
    set-page-backgroundAction

    Saves a custom page background for the currently selected board theme only (Classic or Purple). WebMCP tool arguments are JSON only. Pass the picture as a data URL or raw base64 in `image`, or an http(s) `url`. Use clear: true to remove the image for the current theme only.

    View tool JSON
    {
      "name": "set-page-background",
      "kind": "act",
      "impl": "imperative",
      "description": "Saves a custom page background for the currently selected board theme only (Classic or Purple). WebMCP tool arguments are JSON only. Pass the picture as a data URL or raw base64 in `image`, or an http(s) `url`. Use clear: true to remove the image for the current theme only.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "image": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "clear": {
            "type": "boolean"
          }
        }
      },
      "page": "/triangles"
    }
    how_to_offer_a_hintAction

    Returns instructions for offering an opt-in Give me a hint visualization button in this chat. Takes no arguments. Call this instead of how_to_ask_the_user while the student is solving, before add-lesson-step type riddle (or ask-quiz for a one-off).

    View tool JSON
    {
      "name": "how_to_offer_a_hint",
      "kind": "act",
      "impl": "imperative",
      "description": "Returns instructions for offering an opt-in Give me a hint visualization button in this chat. Takes no arguments. Call this instead of how_to_ask_the_user while the student is solving, before add-lesson-step type riddle (or ask-quiz for a one-off).",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/triangles"
    }
    how_to_ask_the_userAction

    Returns instructions for asking the student in this chat with clickable visualization buttons, not a numbered list and not on the triangle page. Takes no arguments. Call this whenever you need them to choose what happens next, then follow the returned prompt exactly and stop. After anything the student should see on the figure (coach text, a construction, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct GAN objects such as G or ∠C). The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.

    View tool JSON
    {
      "name": "how_to_ask_the_user",
      "kind": "act",
      "impl": "imperative",
      "description": "Returns instructions for asking the student in this chat with clickable visualization buttons, not a numbered list and not on the triangle page. Takes no arguments. Call this whenever you need them to choose what happens next, then follow the returned prompt exactly and stop. After anything the student should see on the figure (coach text, a construction, a demo), call how_to_ask_the_user with no arguments, then follow the returned instructions: render clickable buttons in this chat with your visualization UI. Do not use a numbered list. Do not put the question on the webpage. For a puzzle or exam, call how_to_offer_a_hint, then add-lesson-step with type riddle (question + correct GAN objects such as G or ∠C). The riddle prompt must not spoil how to solve; the student taps Give me a hint in this chat if they want a nudge.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "page": "/triangles"
    }