# Safe MCP leave booking

Use this recipe when an AI client should help prepare a leave request without
silently changing HR data. HollyHR's MCP writes are default-off in production:
`commit_api_write` requires `mcp:write`, `time_off:write`, the tenant
`HOLLYHR_MCP_WRITE_MODE=enabled` gate, and a host that supports MCP form
elicitation.

If any gate is missing, use the flow as a read-only planning assistant and ask a
human to book the leave in HollyHR or through the REST API.

## What it uses

- `whoami`
- `search_people`
- `list_reference`
- `list_time_off`
- `prepare_api_write`
- `commit_api_write`, only after the write gates above are deliberately enabled

The underlying REST operation is `createTimeOff` on `POST /time-off`.

## Scopes

Start read-only:

```text
organisation:read people:read reference:read time_off:read
```

For a controlled write tenant only, add:

```text
time_off:write mcp:write
```

Do not add `people:personal:read`, payroll, document, or webhook-management
scopes for this workflow.

## Prompt

```text
Use HollyHR to prepare a pending time-off request for Pat Example for 2026-07-01
to 2026-07-03.

Rules:
- Use whoami first.
- Find the person with search_people; do not ask for a tenant id.
- Read time-off reference data and existing overlapping requests.
- Do not expose or infer health, sickness, notes, or private reasons.
- If writes are unavailable, stop after showing the exact proposed request.
- If writes are available, call prepare_api_write only after showing the user the
  person, category, dates, and half-day flags.
- Call commit_api_write only after the MCP host displays the approval form and
  the user approves it.
```

## Preparation payload

`prepare_api_write` should freeze the `createTimeOff` request body:

```json
{
  "operation_id": "createTimeOff",
  "args": {
    "body": {
      "person_id": "person_...",
      "category_id": "toc_...",
      "start_date": "2026-07-01",
      "end_date": "2026-07-03",
      "is_from_half_day": false,
      "is_to_half_day": false
    }
  }
}
```

The server signs the frozen payload, captures the idempotency key, and returns a
short-lived confirmation token. The model cannot change the person, dates,
category, half-day flags, ETag, or idempotency key between preparation and
commit.

## Safety checks

- Confirm the person from work identity fields, not home or personal details.
- Check existing `list_time_off` results for the requested date window.
- Use the public category id returned by reference data.
- Keep free-text reasons out of the request. The beta API does not accept notes,
  approval comments, rejection reasons, or health details.
- Do not approve or reject requests through MCP. The beta write surface creates
  or updates pending requests only.

## Failure modes

If `prepare_api_write` reports write mode disabled, missing `mcp:write`, or
missing `time_off:write`, that is expected for normal production tenants. Show
the proposed request and stop.

If `commit_api_write` reports that the host does not support form elicitation,
switch to a human-run REST or in-app flow. Do not ask the model to "just do it"
through `call_api_operation`; generic MCP calls are read-only.
