{
  "openapi": "3.1.1",
  "info": {
    "title": "Tonegrid Scale and Sequence Planner API",
    "version": "1.0.0",
    "summary": "Map a scale to a note grid and plan your melody.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://tonegridscaleplanner.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Map a scale to a note grid and plan your melody.",
        "description": "Inspect the pitches in a configurable Tonegrid scale and turn selected cells into a timed note list.\n\nMethodology:\n- Repeat the chosen scale intervals upward from the root and place the lowest pitch on the last row.\n- Sixteenth-note steps use the same tempo and swing timing as Tonegrid. Cells in the same column play together.\n- Note frequencies use 12-tone equal temperament with A4 at 440 Hz.\n\nThe result shows the first melody cycle only, not an audio rendering or drum sequence. For odd step counts, swing alternates between cycles. Timing assumes a constant tempo.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "tonegrid_scale_planner",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TonegridScalePlannerInput"
              },
              "examples": {
                "example1": {
                  "summary": "C major pentatonic melody",
                  "value": {
                    "root": 48,
                    "scale": "pentatonic",
                    "bpm": 120,
                    "swing": 0,
                    "cells": "1,16\n5,14\n9,12\n13,11"
                  }
                },
                "example2": {
                  "summary": "A minor pentatonic chord with swing",
                  "value": {
                    "root": 57,
                    "scale": "minorPentatonic",
                    "bpm": 90,
                    "swing": 30,
                    "cells": "1,16\n1,14\n1,13\n4,11"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TonegridScalePlannerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "TonegridScalePlannerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "root": {
            "title": "Root note (MIDI number)",
            "description": "48 is C3 and 60 is C4.",
            "type": "number",
            "minimum": 48,
            "maximum": 71,
            "default": 48
          },
          "scale": {
            "title": "Scale",
            "type": "string",
            "enum": [
              "pentatonic",
              "minorPentatonic",
              "major",
              "minor",
              "dorian",
              "mixolydian",
              "harmonicMinor",
              "blues",
              "chromatic"
            ],
            "default": "pentatonic"
          },
          "bpm": {
            "title": "Tempo (BPM)",
            "type": "number",
            "minimum": 40,
            "maximum": 220,
            "default": 120
          },
          "swing": {
            "title": "Swing (%)",
            "description": "Delays alternate steps, like the Tonegrid swing control.",
            "type": "number",
            "minimum": 0,
            "maximum": 45,
            "default": 0
          },
          "rows": {
            "title": "Melody rows",
            "type": "number",
            "minimum": 1,
            "maximum": 24,
            "default": 16
          },
          "steps": {
            "title": "Steps",
            "type": "number",
            "minimum": 1,
            "maximum": 32,
            "default": 16
          },
          "cells": {
            "title": "Selected cells: step,row",
            "description": "One pair per line, counted from 1. Row 1 is the highest pitch; the last row is the root. Leave blank for just the scale.",
            "type": "string",
            "maxLength": 10000,
            "default": "1,16\n5,14\n9,12\n13,11"
          }
        },
        "required": []
      },
      "TonegridScalePlannerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "root",
              "scale",
              "bpm",
              "swing",
              "steps",
              "rows",
              "timePerStep",
              "loopSeconds",
              "notes",
              "events"
            ],
            "properties": {
              "root": {
                "type": "integer"
              },
              "scale": {
                "type": "string"
              },
              "bpm": {
                "type": "integer"
              },
              "swing": {
                "type": "integer"
              },
              "steps": {
                "type": "integer"
              },
              "rows": {
                "type": "integer"
              },
              "timePerStep": {
                "type": "number"
              },
              "loopSeconds": {
                "type": "number"
              },
              "notes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "row",
                    "midi",
                    "note",
                    "frequencyHz"
                  ],
                  "properties": {
                    "row": {
                      "type": "integer"
                    },
                    "midi": {
                      "type": "integer"
                    },
                    "note": {
                      "type": "string"
                    },
                    "frequencyHz": {
                      "type": "number"
                    }
                  }
                }
              },
              "events": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "step",
                    "row",
                    "midi",
                    "note",
                    "frequencyHz",
                    "timeSeconds"
                  ],
                  "properties": {
                    "row": {
                      "type": "integer"
                    },
                    "midi": {
                      "type": "integer"
                    },
                    "note": {
                      "type": "string"
                    },
                    "frequencyHz": {
                      "type": "number"
                    },
                    "step": {
                      "type": "integer"
                    },
                    "timeSeconds": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}