{
  "openapi": "3.1.0",
  "info": {
    "title": "GetFit MCP",
    "version": "1.1.0",
    "description": "Model Context Protocol server for GetFit. Build a workout that fits the time, gear and body someone has. JSON-RPC 2.0 over streamable HTTP; stateless; no authentication for public tools. A personal connector URL (/mcp-server/{token}, minted at https://thegetfit.app/connect.html) adds the person's own tools.",
    "contact": {
      "email": "partnership@thehowtonetwork.com",
      "url": "https://thegetfit.app/for-agents.html"
    }
  },
  "servers": [{ "url": "https://thegetfit.app" }],
  "paths": {
    "/mcp-server": {
      "post": {
        "summary": "Send an MCP JSON-RPC message",
        "description": "Methods: initialize, ping, tools/list, tools/call, notifications/*. Public tools: build_workout, search_workouts, get_workout, list_contributors, get_contributor.",
        "operationId": "mcpRpc",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/JsonRpcRequest" },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": { "name": "build_workout", "arguments": { "focus": "legs", "minutes": 30, "equipment": "from home", "avoid": ["knees"] } }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "JSON-RPC response (or an array for a batch).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcResponse" } } } },
          "202": { "description": "Accepted notification; no body." },
          "400": { "description": "Parse error, invalid request, or a batch over 10 messages." },
          "429": {
            "description": "Too many requests from this client (over 300 calls a minute).",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" }, "retry_after": { "type": "integer" } } } } }
          }
        }
      },
      "get": { "summary": "Not supported", "operationId": "mcpGet", "responses": { "405": { "description": "This endpoint speaks JSON-RPC over POST only." } } }
    },
    "/mcp-server/{token}": {
      "post": {
        "summary": "Personal connector",
        "description": "Same protocol; adds my_profile, build_plan, my_schedule, my_history, a personal build_workout (saved to their library, private unless publish:true), and list/create/update/publish/delete for their workouts.",
        "operationId": "mcpPersonalRpc",
        "parameters": [{ "name": "token", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Personal connector token from /connect.html. Treat it like a password." }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcRequest" } } } },
        "responses": {
          "200": { "description": "JSON-RPC response.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcResponse" } } } },
          "401": { "description": "Invalid or revoked connector token." }
        }
      }
    },
    "/mcp": {
      "post": { "summary": "Redirects to /mcp-server", "operationId": "mcpRedirect", "responses": { "308": { "description": "Permanent redirect to /mcp-server (method and body preserved)." } } }
    }
  },
  "components": {
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": ["jsonrpc", "method"],
        "properties": {
          "jsonrpc": { "const": "2.0" },
          "id": { "type": ["string", "integer", "null"] },
          "method": { "type": "string" },
          "params": { "type": ["object", "null"] }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "properties": {
          "jsonrpc": { "const": "2.0" },
          "id": { "type": ["string", "integer", "null"] },
          "result": {
            "type": "object",
            "description": "For tools/call: { content: [{type:'text', text}], structuredContent: { summary, ... }, isError? }. Errors carry message, suggestion and, when rate-limited, retry_after."
          },
          "error": { "type": "object", "properties": { "code": { "type": "integer" }, "message": { "type": "string" } } }
        }
      }
    }
  }
}
