{
  "openapi": "3.1.1",
  "info": {
    "title": "ODE Solver (Runge–Kutta) API",
    "version": "1.0.0",
    "summary": "Solve y′ = f(t, y) and systems with adaptive RK45 or RK4: table, plots and CSV.",
    "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://prooflineodesolver.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Solve y′ = f(t, y) and systems with adaptive RK45 or RK4: table, plots and CSV.",
        "description": "Type a differential equation or a system such as x′ = v, v′ = −x with initial values and parameters, and get the solution table, a plot of every variable, a phase portrait for two variables and a CSV download. Uses the adaptive Dormand–Prince RK45 method with error control or classical fixed-step RK4, and reports steps and function evaluations. Part of the Proofline math notebook.\n\nMethodology:\n- Right-hand sides are read by Proofline’s own expression parser (no eval) and may use the independent variable, all state variables and the parameters.\n- RK45: Dormand–Prince 5(4) embedded pair with local extrapolation and FSAL; the step is accepted when the RMS of error/(atol + rtol·|y|) ≤ 1 and adapted by 0.9·err^(−1/5), limited to a factor 0.2…5.\n- RK4: classical fourth-order Runge–Kutta with a fixed step.\n- Both methods shorten the step before each output time so the table holds computed values, not interpolations.\n- Verified against exact solutions (exponential decay, harmonic oscillator) and the conserved quantity of the Lotka–Volterra system.\n\nExplicit Runge–Kutta methods are not suited to stiff systems (very different time scales): the step size collapses and the solver stops with a message. Tolerances bound the error per step, not the global error.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "proofline_ode_solver",
        "x-owner-app": "proofline",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProoflineOdeSolverInput"
              },
              "examples": {
                "example1": {
                  "summary": "Exponential decay y′ = −k·y",
                  "value": {
                    "equations": "y' = -k*y",
                    "initial": "y = 1",
                    "parameters": "k = 0.5",
                    "tEnd": 10
                  }
                },
                "example2": {
                  "summary": "Harmonic oscillator as a system",
                  "value": {
                    "equations": "x' = v\nv' = -omega^2*x",
                    "initial": "x = 1, v = 0",
                    "parameters": "omega = 2",
                    "tEnd": 6.283185307179586,
                    "outputPoints": 201
                  }
                },
                "example3": {
                  "summary": "Lotka–Volterra predator and prey",
                  "value": {
                    "equations": "prey' = a*prey - b*prey*pred\npred' = d*prey*pred - c*pred",
                    "initial": "prey = 10, pred = 5",
                    "parameters": "a = 1.1, b = 0.4, c = 0.4, d = 0.1",
                    "tEnd": 50,
                    "outputPoints": 501
                  }
                },
                "example4": {
                  "summary": "Logistic growth with RK4",
                  "value": {
                    "equations": "dN/dt = r*N*(1 - N/K)",
                    "initial": "N = 10",
                    "parameters": "r = 0.8, K = 1000",
                    "tEnd": 20,
                    "method": "rk4",
                    "step": 0.05
                  }
                },
                "example5": {
                  "summary": "Damped pendulum",
                  "value": {
                    "equations": "theta' = w\nw' = -g/L*sin(theta) - c*w",
                    "initial": "theta = 2.5, w = 0",
                    "parameters": "g = 9.81, L = 1, c = 0.3",
                    "tEnd": 20,
                    "outputPoints": 401
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProoflineOdeSolverResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "ProoflineOdeSolverInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "equations": {
            "title": "Equations",
            "description": "One equation per line: y' = expression or dy/dt = expression. Right-hand sides may use the independent variable, every state variable and the parameters. Use + − * / ^, implicit products (2x), sin, cos, tan, exp, ln (natural log), log (base 10), sqrt, abs, pi and e. Angles are in radians.",
            "type": "string",
            "maxLength": 6000
          },
          "initial": {
            "title": "Initial values",
            "description": "One value per state variable at the start time, e.g. x = 1, v = 0.",
            "type": "string",
            "maxLength": 1000
          },
          "parameters": {
            "title": "Parameters",
            "description": "Optional constants used in the equations, e.g. a = 1.1, b = 0.4.",
            "type": "string",
            "maxLength": 1000
          },
          "variable": {
            "title": "Independent variable",
            "type": "string",
            "maxLength": 20,
            "default": "t"
          },
          "tStart": {
            "title": "Start time",
            "type": "number",
            "default": 0
          },
          "tEnd": {
            "title": "End time",
            "type": "number",
            "default": 10
          },
          "method": {
            "title": "Method",
            "type": "string",
            "enum": [
              "rk45",
              "rk4"
            ],
            "default": "rk45"
          },
          "tolerance": {
            "title": "Tolerance (RK45)",
            "description": "Relative error allowed per step; the absolute tolerance is 1/100 of it.",
            "type": "number",
            "minimum": 1e-13,
            "maximum": 0.01,
            "default": 1e-8
          },
          "step": {
            "title": "Step size (RK4)",
            "description": "Default: 1/1000 of the interval.",
            "type": "number",
            "minimum": 0
          },
          "outputPoints": {
            "title": "Output points",
            "description": "Equally spaced times in the table, plot and CSV (start and end included).",
            "type": "integer",
            "minimum": 2,
            "maximum": 2001,
            "default": 101
          }
        },
        "required": [
          "equations",
          "initial"
        ]
      },
      "ProoflineOdeSolverResult": {
        "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": [
              "variable",
              "states",
              "method",
              "tStart",
              "tEnd",
              "times",
              "values",
              "finalValues",
              "steps",
              "rejectedSteps",
              "evaluations",
              "completed",
              "message"
            ],
            "properties": {
              "variable": {
                "type": "string"
              },
              "states": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "method": {
                "type": "string",
                "enum": [
                  "rk45",
                  "rk4"
                ]
              },
              "tStart": {
                "type": "number"
              },
              "tEnd": {
                "type": "number"
              },
              "times": {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              "values": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                },
                "description": "One row per output time, values in the order of `states`."
              },
              "finalValues": {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              "steps": {
                "type": "integer"
              },
              "rejectedSteps": {
                "type": "integer"
              },
              "evaluations": {
                "type": "integer"
              },
              "completed": {
                "type": "boolean"
              },
              "message": {
                "type": "string"
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}