{"openapi":"3.1.0","info":{"title":"ClimbGrade API","version":"0.1.0","description":"A fully local bouldering training-log analytics connector: a grade pyramid with a shape check, a rolling hardest-grade-sent tracker, an attempts-to-send ratio per grade, and a trend-based next-grade projection, computed from a caller-supplied session log (nothing stored), plus a compact V-scale/Font/YDS/French/UIAA grade-conversion reference table.\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://climbgrade.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"hr@unifydynamics.com","url":"https://connectorbay.com/climbgrade/docs"},"termsOfService":"https://connectorbay.com/climbgrade/terms"},"servers":[{"url":"https://climbgrade.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/climbgrade/docs"},"security":[{},{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/grade_conversion_table":{"post":{"operationId":"grade_conversion_table","summary":"Converts a grade between V-scale, Font, YDS, French and UIAA using a compact, reference-only table (14","description":"Converts a grade between V-scale, Font, YDS, French and UIAA using a compact, reference-only table (14\n    milestone rows, VB through V12) — smaller and coarser than the sibling /ascent connector's fuller,\n    independently cross-checked table. Omit `grade` to get the whole compact table at once. Use this to translate\n    an occasional roped-route grade into its approximate V-scale bucket before logging it with climbgrade's\n    training-log tools, which work in V-scale. Conversions here are approximate, not exact. Use for \"what's V4 in\n    French\", \"convert 5.12a to V-scale\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"system":{"default":"v_scale","description":"v_scale | font | yds | french | uiaa. Ignored if grade is omitted.","title":"System","type":"string"},"grade":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"A specific grade to convert.","examples":["V4","6B","5.12a","7a+","IX"],"title":"Grade"}},"title":"grade_conversion_tableArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/grade_pyramid":{"post":{"operationId":"grade_pyramid","summary":"Builds a bouldering grade pyramid from your training log: counts sends per V-scale tier and checks the","description":"Builds a bouldering grade pyramid from your training log: counts sends per V-scale tier and checks the\n    shape against the classic 'wide base, narrower near your limit' pattern, flagging any tier with MORE sends\n    than an easier tier below it — a common top-heavy/plateau warning sign, not a badge of honor. Stateless: bring\n    your own session log each call. Use for \"build my grade pyramid\", \"is my climbing pyramid top-heavy\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"session_log":{"description":"Your training log, a non-empty list of session objects: {date: 'YYYY-MM-DD', grade: a V-scale string like 'V4' or 'VB' (optionally with a +/- modifier), attempts: positive integer, sent: true/false}. Bring your own log on every call — nothing is stored server-side between calls.","items":{"additionalProperties":true,"type":"object"},"title":"Session Log","type":"array"}},"required":["session_log"],"title":"grade_pyramidArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/hardest_grade_progression":{"post":{"operationId":"hardest_grade_progression","summary":"Sorts your training log chronologically (regardless of what order you pass the sessions in) and returns,","description":"Sorts your training log chronologically (regardless of what order you pass the sessions in) and returns,\n    for each session's date, the running hardest V-scale grade you had actually sent as of that date. Use for\n    \"what's my hardest grade sent over time\", \"when did I first send V5\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"session_log":{"description":"Your training log, a non-empty list of session objects: {date: 'YYYY-MM-DD', grade: a V-scale string like 'V4' or 'VB' (optionally with a +/- modifier), attempts: positive integer, sent: true/false}. Bring your own log on every call — nothing is stored server-side between calls.","items":{"additionalProperties":true,"type":"object"},"title":"Session Log","type":"array"}},"required":["session_log"],"title":"hardest_grade_progressionArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/attempts_to_send_ratio":{"post":{"operationId":"attempts_to_send_ratio","summary":"Groups every session in your training log by V-scale grade and reports, per tier, total sessions, total","description":"Groups every session in your training log by V-scale grade and reports, per tier, total sessions, total\n    attempts, sends, attempts-per-send, and send rate. Use for \"what's my attempts-to-send ratio by grade\", \"how\n    many tries does it take me to send a V5 on average\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"session_log":{"description":"Your training log, a non-empty list of session objects: {date: 'YYYY-MM-DD', grade: a V-scale string like 'V4' or 'VB' (optionally with a +/- modifier), attempts: positive integer, sent: true/false}. Bring your own log on every call — nothing is stored server-side between calls.","items":{"additionalProperties":true,"type":"object"},"title":"Session Log","type":"array"}},"required":["session_log"],"title":"attempts_to_send_ratioArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/next_grade_projection":{"post":{"operationId":"next_grade_projection","summary":"Fits an ordinary least-squares trend line to your sent grades over time and extrapolates a rough estimate","description":"Fits an ordinary least-squares trend line to your sent grades over time and extrapolates a rough estimate\n    of the V-scale grade you might be sending horizon_days from your last logged session. Needs at least two sent\n    sessions on two different dates; returns sufficient_data: false with a plain explanation otherwise. Clearly a\n    rough trend extrapolation from your own data, never a guarantee or a coaching plan. Use for \"at this rate,\n    what grade might I be sending in two months\", \"project my next grade\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"session_log":{"description":"Your training log, a non-empty list of session objects: {date: 'YYYY-MM-DD', grade: a V-scale string like 'V4' or 'VB' (optionally with a +/- modifier), attempts: positive integer, sent: true/false}. Bring your own log on every call — nothing is stored server-side between calls.","items":{"additionalProperties":true,"type":"object"},"title":"Session Log","type":"array"},"horizon_days":{"default":60,"description":"How many days ahead to project.","maximum":730,"minimum":1,"title":"Horizon Days","type":"integer"}},"required":["session_log"],"title":"next_grade_projectionArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/training_log_summary":{"post":{"operationId":"training_log_summary","summary":"Runs grade_pyramid, hardest_grade_progression, attempts_to_send_ratio and next_grade_projection on the same","description":"Runs grade_pyramid, hardest_grade_progression, attempts_to_send_ratio and next_grade_projection on the same\n    training log in one call and returns them together with overall session/date-range stats. Use for \"give me a\n    full breakdown of my climbing log\", \"summarize my training progress\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"session_log":{"description":"Your training log, a non-empty list of session objects: {date: 'YYYY-MM-DD', grade: a V-scale string like 'V4' or 'VB' (optionally with a +/- modifier), attempts: positive integer, sent: true/false}. Bring your own log on every call — nothing is stored server-side between calls.","items":{"additionalProperties":true,"type":"object"},"title":"Session Log","type":"array"},"projection_horizon_days":{"default":60,"description":"Horizon in days for the bundled next-grade projection.","maximum":730,"minimum":1,"title":"Projection Horizon Days","type":"integer"}},"required":["session_log"],"title":"training_log_summaryArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}