{
  "descriptorVersion": "1.0.0",
  "name": "plan_leave",
  "title": "Hong Kong annual-leave planner (general holidays)",
  "description": "Find Hong Kong annual-leave plans that create a long break around gazetted general (public/bank) holidays. Uses only the arguments given: it REPLACES all of this page's planner inputs, including any company holidays entered earlier (they are cleared and never returned), then shows the same plans on screen. Calculation is local; nothing is stored. Only gazetted holidays are used and no break runs past the end of gazetted data; estimated future-year holidays are never used. Statutory (labour) holidays, rest-day substitution and employment entitlements are not modelled by this tool. Calculation or source matching runs in this page; arguments and results are not uploaded to Agoodeal servers or to Google Analytics, and the result is returned only to the calling agent. Non-sensitive usage metadata (tool name, outcome, execution mode, error code, duration; predefined source IDs for source matching) is reported through the site’s existing Google Analytics 4.",
  "execution": {
    "environment": "browser",
    "interface": "WebMCP imperative API: document.modelContext.registerTool (experimental)",
    "pageUrls": [
      "https://www.agoodeal.com/tools/leave-planner/"
    ],
    "requirement": "Open one of pageUrls in a browser that exposes document.modelContext. As of October 2026 this is experimental: Chrome 149+ with chrome://flags/#enable-webmcp-testing, or an origin trial that Agoodeal has not joined. Without it the page works normally for people and no tool is registered.",
    "serverEndpoint": null,
    "argumentsEncoding": "JSON object (some browser versions require callers to pass it as a JSON string).",
    "returns": "A JSON string matching outputSchema."
  },
  "annotations": {
    "readOnlyHint": false,
    "untrustedContentHint": false,
    "consequentialHint": false
  },
  "annotationNotes": "readOnlyHint is false because the tool replaces the planner inputs and results shown on the page. It submits, stores and books nothing.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "minimumDays": {
        "type": "integer",
        "minimum": 3,
        "maximum": 62,
        "description": "Minimum consecutive days off wanted, counting weekends/rest days and holidays."
      },
      "maximumLeave": {
        "type": "integer",
        "minimum": 0,
        "maximum": 30,
        "description": "Maximum annual-leave days the person is willing to use for one break."
      },
      "period": {
        "type": "string",
        "enum": [
          "upcoming",
          "2026",
          "2027"
        ],
        "default": "upcoming",
        "description": "upcoming = breaks starting from today (Hong Kong date) up to the end of gazetted holiday data; a year = breaks overlapping that year. Past years are rejected."
      },
      "workweek": {
        "type": "string",
        "enum": [
          "mon-fri",
          "mon-sat"
        ],
        "default": "mon-fri",
        "description": "Regular working days. Custom or shift patterns are not supported by this tool."
      },
      "companyHolidays": {
        "type": "array",
        "items": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "maxItems": 20,
        "uniqueItems": true,
        "default": [],
        "description": "Optional extra employer-specific days off (YYYY-MM-DD) supplied for this request. Replaces any company holidays already on the page."
      },
      "limit": {
        "type": "integer",
        "minimum": 1,
        "maximum": 12,
        "default": 5,
        "description": "Maximum number of plans returned."
      }
    },
    "required": [
      "minimumDays",
      "maximumLeave"
    ],
    "additionalProperties": false
  },
  "outputSchema": {
    "oneOf": [
      {
        "type": "object",
        "required": [
          "ok",
          "tool",
          "uiInputsReplaced",
          "arguments",
          "evaluatedOnHongKongDate",
          "gazettedCoverage",
          "maximumAchievableDays",
          "shownOnPageCount",
          "omittedBeyondGazettedCoverage",
          "plans",
          "source",
          "notes"
        ],
        "properties": {
          "ok": {
            "const": true
          },
          "tool": {
            "const": "plan_leave"
          },
          "uiInputsReplaced": {
            "const": true
          },
          "arguments": {
            "type": "object"
          },
          "holidaySystem": {
            "type": "string"
          },
          "evaluatedOnHongKongDate": {
            "type": "string",
            "format": "date"
          },
          "window": {
            "type": "object",
            "required": [
              "earliestStart",
              "overlapStart",
              "overlapEnd",
              "latestEnd"
            ],
            "description": "Every returned plan starts on or after earliestStart, overlaps [overlapStart, overlapEnd] by at least one day, and ends on or before latestEnd. A plan for a year may therefore start in the previous December.",
            "properties": {
              "earliestStart": {
                "type": "string",
                "format": "date",
                "description": "Hong Kong date of the request (today). No plan starts earlier."
              },
              "overlapStart": {
                "type": "string",
                "format": "date",
                "description": "First day of the requested period: 1 January for a year, or today for upcoming."
              },
              "overlapEnd": {
                "type": "string",
                "format": "date",
                "description": "Last day of the requested period."
              },
              "latestOverlap": {
                "type": "string",
                "format": "date",
                "description": "Alias of overlapEnd, kept for compatibility with the first draft."
              },
              "latestEnd": {
                "type": "string",
                "format": "date",
                "description": "Last gazetted holiday-data date. No plan ends later."
              }
            }
          },
          "gazettedCoverage": {
            "type": "object",
            "properties": {
              "start": {
                "type": "string",
                "format": "date"
              },
              "end": {
                "type": "string",
                "format": "date"
              }
            }
          },
          "maximumAchievableDays": {
            "type": "integer"
          },
          "shownOnPageCount": {
            "type": "integer"
          },
          "omittedBeyondGazettedCoverage": {
            "type": "integer",
            "description": "Defensive count; 0 when the page rendered the bounded calculation."
          },
          "plans": {
            "type": "array",
            "maxItems": 12,
            "items": {
              "type": "object",
              "required": [
                "start",
                "end",
                "totalDays",
                "leaveDaysUsed",
                "leaveDates",
                "generalHolidays",
                "companyHolidays",
                "lastWorkingDay",
                "returnDate"
              ],
              "properties": {
                "start": {
                  "type": "string",
                  "format": "date"
                },
                "end": {
                  "type": "string",
                  "format": "date"
                },
                "totalDays": {
                  "type": "integer"
                },
                "leaveDaysUsed": {
                  "type": "integer"
                },
                "leaveDates": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "date"
                  }
                },
                "generalHolidays": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "date",
                      "name"
                    ],
                    "properties": {
                      "date": {
                        "type": "string",
                        "format": "date"
                      },
                      "name": {
                        "type": "string"
                      }
                    }
                  }
                },
                "companyHolidays": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "date"
                  }
                },
                "lastWorkingDay": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                },
                "returnDate": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date",
                  "description": "null when it would fall after gazetted holiday data."
                }
              },
              "additionalProperties": false
            }
          },
          "source": {
            "type": "object"
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "const": false
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "enum": [
                  "invalid_json",
                  "invalid_argument",
                  "period_past",
                  "coverage_ended",
                  "no_plan_available",
                  "target_unachievable",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              },
              "field": {
                "type": "string"
              },
              "maximumAchievableDays": {
                "type": "integer"
              }
            }
          }
        }
      }
    ]
  },
  "privacy": "Uses only the arguments supplied. Existing page inputs, including company holidays typed by the visitor, are replaced and are never read into or returned by the tool. Nothing is stored or logged. Calculation or source matching runs in this page; arguments and results are not uploaded to Agoodeal servers or to Google Analytics, and the result is returned only to the calling agent. Non-sensitive usage metadata (tool name, outcome, execution mode, error code, duration; predefined source IDs for source matching) is reported through the site’s existing Google Analytics 4.",
  "dataSource": {
    "name": "1823 Hong Kong general holidays",
    "url": "https://data.gov.hk/tc-data/dataset/hk-dpo-statistic-cal",
    "gazettedYears": "2025-2027"
  },
  "scope": "Gazetted general holidays only. Estimated holidays are excluded before calculation and no break, company holiday or maximum may extend past the last gazetted date (currently 2027-12-31). While a tool result is shown the page uses the same bounded calculation and says so; any visitor change returns the page to its normal behaviour."
}
