{
  "openapi": "3.1.0",
  "info": {
    "title": "TripTiming AI Agent API & MCP Tools",
    "version": "1.0.0",
    "description": "Authoritative empirical travel timing intelligence across 100 top global destinations. Evaluates carry capacity crowds, ERA5 climate reanalysis, seasonal pricing curves, and local events to provide definitive optimal visit windows and timing arbitrage.",
    "contact": {
      "name": "TripTiming Intelligence",
      "url": "https://triptiming.xyz"
    }
  },
  "servers": [
    {
      "url": "https://triptiming.xyz",
      "description": "Production Vercel Edge Server"
    }
  ],
  "paths": {
    "/api/timing": {
      "get": {
        "operationId": "getTripTiming",
        "summary": "Get destination timing score, comfort metrics, and recommended window",
        "description": "Queries TripTiming's empirical index for a specified destination on an exact date or month. Returns evaluated scores, crowd levels, weather conditions, lodging tier descriptions, and direct booking links.",
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "required": true,
            "description": "City name or ID (e.g. 'tokyo', 'kyoto', 'paris', 'rome')",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Specific date in YYYY-MM-DD format (e.g. '2026-05-20')",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Calendar month (1 to 12) for monthly aggregate evaluation",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            }
          },
          {
            "name": "lens",
            "in": "query",
            "required": false,
            "description": "Traveler persona lens preference",
            "schema": {
              "type": "string",
              "enum": ["sweet_spot", "quiet", "value", "nightlife"],
              "default": "sweet_spot"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Evaluated travel timing dossier",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimingResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid city or date parameters"
          },
          "404": {
            "description": "City not found"
          }
        }
      }
    },
    "/api/arbitrage": {
      "get": {
        "operationId": "checkDateArbitrage",
        "summary": "Detect high-yield timing arbitrage for suboptimal dates",
        "description": "Scans adjacent departure dates (±searchRadius) to determine if shifting the trip by a few days yields substantially higher comfort, lower crowd friction, or significant lodging savings.",
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "required": true,
            "description": "City name or ID (e.g. 'tokyo', 'kyoto')",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "Target departure date (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "radius",
            "in": "query",
            "required": false,
            "description": "Search radius in days (default: 21, min: 7, max: 35)",
            "schema": {
              "type": "integer",
              "default": 21
            }
          },
          {
            "name": "lens",
            "in": "query",
            "required": false,
            "description": "Traveler persona lens preference",
            "schema": {
              "type": "string",
              "enum": ["sweet_spot", "quiet", "value", "nightlife"],
              "default": "sweet_spot"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Timing arbitrage calculation results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArbitrageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters"
          }
        }
      }
    },
    "/api/radar": {
      "get": {
        "operationId": "findGoldenDestinations",
        "summary": "Global Date Radar: Discover where in the world is optimal for a date window",
        "description": "Ranks all 100 destinations worldwide for arbitrary travel dates to identify which cities are currently experiencing their Golden or Favorable travel window.",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "description": "Departure start date in YYYY-MM-DD format",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "duration",
            "in": "query",
            "required": false,
            "description": "Trip duration in days (3 to 21, default: 7)",
            "schema": {
              "type": "integer",
              "default": 7
            }
          },
          {
            "name": "continent",
            "in": "query",
            "required": false,
            "description": "Geographic continent filter",
            "schema": {
              "type": "string",
              "enum": ["all", "europe", "asia", "americas", "other"],
              "default": "all"
            }
          },
          {
            "name": "lens",
            "in": "query",
            "required": false,
            "description": "Traveler persona lens preference",
            "schema": {
              "type": "string",
              "enum": ["sweet_spot", "quiet", "value", "nightlife"],
              "default": "sweet_spot"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked destinations for the selected window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RadarResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/mcp": {
      "post": {
        "operationId": "handleMcpRpc",
        "summary": "Model Context Protocol (MCP) JSON-RPC 2.0 endpoint",
        "description": "Standard JSON-RPC 2.0 endpoint supporting `tools/list` and `tools/call` for direct integration into Claude Desktop, Cursor, and MCP clients.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["jsonrpc", "method"],
                "properties": {
                  "jsonrpc": { "type": "string", "example": "2.0" },
                  "method": { "type": "string", "enum": ["tools/list", "tools/call", "ping"] },
                  "params": { "type": "object" },
                  "id": { "oneOf": [{ "type": "string" }, { "type": "integer" }] }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TimingResponse": {
        "type": "object",
        "properties": {
          "city": { "type": "string" },
          "country": { "type": "string" },
          "date": { "type": "string" },
          "tripTimingIndex": { "type": "integer", "minimum": 0, "maximum": 100 },
          "tier": { "type": "string", "enum": ["golden", "favorable", "moderate", "friction"] },
          "tierLabel": { "type": "string" },
          "verdict": { "type": "string" },
          "weather": {
            "type": "object",
            "properties": {
              "tempC": { "type": "number" },
              "tempF": { "type": "number" },
              "condition": { "type": "string" },
              "rainChancePercent": { "type": "integer" }
            }
          },
          "crowdLevel": { "type": "string" },
          "lodgingPricing": { "type": "string" },
          "bookingUrl": { "type": "string", "format": "uri" },
          "flightUrl": { "type": "string", "format": "uri" }
        }
      },
      "ArbitrageResponse": {
        "type": "object",
        "properties": {
          "hasArbitrage": { "type": "boolean" },
          "isAlreadyOptimal": { "type": "boolean" },
          "scoreDelta": { "type": "integer" },
          "headline": { "type": "string" },
          "directionLabel": { "type": "string" },
          "daysDifference": { "type": "integer" },
          "originalWindow": { "type": "object" },
          "shiftedWindow": { "type": "object" },
          "rationales": {
            "type": "array",
            "items": { "type": "string" }
          },
          "bookingUrl": { "type": "string", "format": "uri" },
          "flightUrl": { "type": "string", "format": "uri" }
        }
      },
      "RadarResponse": {
        "type": "object",
        "properties": {
          "startDate": { "type": "string" },
          "durationDays": { "type": "integer" },
          "totalEvaluated": { "type": "integer" },
          "destinations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rank": { "type": "integer" },
                "city": { "type": "string" },
                "country": { "type": "string" },
                "tripTimingIndex": { "type": "integer" },
                "tier": { "type": "string" },
                "tierLabel": { "type": "string" },
                "avgTempC": { "type": "number" },
                "bookingUrl": { "type": "string", "format": "uri" }
              }
            }
          }
        }
      }
    }
  }
}
