# For developers: tool reference

The Kalender Sync MCP server (`https://app.kalender-sync.de/mcp`, Streamable HTTP) exposes up to **seven tools**.

Two properties apply to every tool:

- **Visibility gating:** each tool only sees the calendars you shared, and per calendar only the allowed [detail level](https://docs.kalender-sync.de/en/ki-assistent/sichtbarkeit/). Calendars you did not share do not exist for the server.
- **Dynamic tool list:** the four write tools only appear when your access may write ([granted per calendar](https://docs.kalender-sync.de/en/ki-assistent/schreibzugriff/)). A read-only access sees 4 tools — we don't ship tools that would always refuse. If you change write permissions later, the tools only show up once the client [reloads the tool list](https://docs.kalender-sync.de/en/ki-assistent/schreibzugriff/#enabling-write-access-later).

## Read tools

### `list_calendars`

Lists the shared calendars with their detail level. `readable: false` marks calendars that can't be read right now (they are then missing from every other answer too — and are deliberately listed rather than omitted). `writable: true` marks the calendars this access may create events in — that is where the `calendar_id` for `create_event` comes from. `sync_health` additionally shows the state of Kalender Sync's own synchronisation of that calendar, if it takes part in one.

*Parameters: none.*

### `get_availability`

Returns the events in a range, across all shared calendars. Every calendar is read **directly at the provider** (no copy); reads are reused for up to 60 seconds. Everything is included except cancelled events — all-day events and "tentative" ones too. If a calendar could not be read, that appears in `sources` and `warnings` — an answer never claims a completeness it doesn't have.

Per entry, `blocks_time` says whether it actually occupies the time. It is `false` for entries that don't make you unavailable: holidays, birthdays, and **every all-day event from Apple/iCloud**, which that provider always marks as free with no setting for you to change. Such an entry is still a real appointment — an all-day "Baustelle Darmstadt" is a working day, not free time. So for "am I free?" only `blocks_time: true` counts, while "what do I have on?" counts everything.

| Parameter | Required | Description |
| --- | --- | --- |
| `from` / `to` | yes | Range, ISO 8601. Max span 92 days, lookback bounded to 365 days. |

### `search_events`

Finds events by text — case-insensitive substring over title, location and description. The search is deliberately **a filter over the same visibility-rendered data `get_availability` returns**, not a second read path: calendars on the "busy only" level carry no titles and therefore can never match — the answer says so as a warning. "No match" is never proof that the event doesn't exist.

| Parameter | Required | Description |
| --- | --- | --- |
| `query` | yes | Search text (min. 2 characters) |
| `from` / `to` | no | Range as in `get_availability`; default −7 to +85 days |

At most 50 matches (the chronologically earliest), `truncated` signals when the cap was hit.

### `send_feedback`

Sends the user's feedback to the Kalender Sync team — for example when they wanted something the tools can't do yet. The assistant is instructed to use this **only on the user's explicit request**. `contact_ok` (default: off) permits exactly **one** topical reply from us — no newsletter, no mailing list. Processing details in the [privacy policy, section 3.10](https://kalender-sync.de/en/privacy-policy/).

| Parameter | Required | Description |
| --- | --- | --- |
| `message` | yes | The feedback (10–2000 characters) |
| `category` | yes | `missing_capability` · `bug` · `other` |
| `contact_ok` | no | Only if the user explicitly agreed to a single reply |

## Write tools (all plans, granted per calendar)

Two separate permissions per calendar: **create events** and, below it, **change and delete existing events**. Without the second, the assistant can only touch what it created itself — your existing events are then technically not addressable. More under [write access](https://docs.kalender-sync.de/en/ki-assistent/schreibzugriff/).

### `create_event`

Creates an event in a writable calendar. Availability is **checked live at write time** (not from cache): an overlap does not prevent creation but comes back as a warning — whether to double-book is the user's call. Only entries that actually occupy the time are counted (`blocks_time: true`). Holidays, birthdays and all-day events from Apple/iCloud deliberately raise no warning, since otherwise every booking on a holiday would look like a clash. So no warning does not mean the day is empty. `start`/`end` require ISO 8601 **with a timezone**; `calendar_id` is only needed with several writable calendars — `list_calendars` shows which those are via `writable: true`. If it is omitted with several, the error message names the permitted calendars.

### `update_event` · `delete_event`

Update or delete an event. Two kinds are addressable:

1. **Events this access created itself** (via the `event_id` from `create_event`) — always.
2. **Existing events** in a calendar you granted "change and delete" for — via the `event_id` from `get_availability` or `search_events`.

The second kind has four conditions, and every refusal names the way forward: the calendar is granted, shared at **All details**, the event is **not a synchronised copy** (otherwise the next sync overwrites the change — the refusal names the source calendar), and **you are the organiser**. Someone else's invitation cannot be rewritten; `respond_to_event` handles those.

Events that are not addressable answer `not_found`, not `forbidden` — so existence is not even confirmed. Deletions are executed at the provider and propagate into mirrored calendars through the normal sync. Both tools carry the MCP annotation `destructiveHint: true`.

### `respond_to_event`

Answers **someone else's invitation**: accept, decline or tentatively accept. The organiser is notified — that is the point: merely deleting an invitation removes it locally and leaves them expecting you.

The permission is the same one as for changing, but the condition is the **inverse**: changing requires you to be the organiser, answering requires you not to be. For a **recurring** appointment `scope` is needed — `occurrence` answers that date only, `series` answers all of them. Without it the assistant asks rather than guesses: a decline sent to the organiser cannot be taken back.

Available for **Google and Microsoft**. Other providers do not forward answers to the organiser; there the tool points at the calendar app instead of sending an answer nobody receives.

## Logging

Every tool call lands in the [access log](https://docs.kalender-sync.de/en/ki-assistent/) as **metadata** — timestamp, tool, calendars concerned, outcome. Never the content of your events, never the search text, never the feedback wording.

---

*As of server version 1.3.0 (2026-09-10). The server is listed in the [official MCP Registry](https://registry.modelcontextprotocol.io/v0.1/servers?search=de.kalender-sync) as `de.kalender-sync/kalender-sync`. It rebuilds the tool list on every connection, but clients cache it — after a permission change you have to [reload it](https://docs.kalender-sync.de/en/ki-assistent/schreibzugriff/#enabling-write-access-later) in your client.*