# Tools

Die vier Tools des MCP-Servers von plnnrly: was jedes annimmt und zurückgibt und welche Limits gelten.

Der MCP-Server hat kein Tool pro Funktion. Über drei allgemeine Tools erreicht ein KI-Client jede Operation der [REST-API (Englisch)](https://developers.plnnrly.com/en/docs/api/v2/) außer Datei-Uploads, immer in Ihrem Namen und mit Ihren Rechten. Ein viertes Tool gibt Ihr eigenes Profil zurück. Bekommt die API eine neue Funktion, können Clients sie sofort nutzen.

| Tool                    | Titel im Client   | Was es tut                                |
| ----------------------- | ----------------- | ----------------------------------------- |
| `search_api`            | Search the API    | Findet API-Operationen und beschreibt sie |
| `api_read`              | Read from the API | Sendet ein `GET` an eine API-Operation    |
| `api_write`             | Write to the API  | Sendet ein `POST`, `PATCH` oder `DELETE`  |
| `get-current-user-tool` | Get current user  | Gibt Ihr Profil zurück                    |

Drei Tools lesen nur. **Write to the API** ist als Tool gekennzeichnet, das Daten ändern kann, deshalb fragen Clients standardmäßig nach Ihrer Zustimmung. In den meisten Clients können Sie es für ein Gespräch oder dauerhaft erlauben. [Rechte und Sicherheit](https://developers.plnnrly.com/de/docs/mcp/permissions-and-safety/) erklärt, was ein Client darf.

## Wie ein Client die Tools nutzt

Jeder Client bekommt vom Server außerdem eine kurze Anleitung. Sie beschreibt drei Schritte: die Operation mit `search_api` finden, lesen, was sie annimmt, und sie dann mit `api_read` oder `api_write` aufrufen. Außerdem erfährt der Client daraus, dass:

- Pfade von Arbeitselementen Schlüssel wie `ACM-12` akzeptieren
- Benutzerfilter `me` akzeptieren
- Löschen `confirm: true` braucht, das erst nach Ihrer Zustimmung gesendet wird, und nur funktioniert, wenn Ihre Organisation es erlaubt
- Text mit `mode: append` an ein Drive-Dokument angefügt wird, weil sonst das ganze Dokument ersetzt wird

## search_api

Findet API-Operationen und beschreibt sie. Das Tool liefert nur die Dokumentation der API, nie Daten aus Ihrer Organisation.

| Eingabe        | Typ    | Pflicht | Beschreibung                                                             |
| -------------- | ------ | ------- | ------------------------------------------------------------------------ |
| `query`        | string | nein    | Suchbegriffe wie `link work items` oder `log time`.                      |
| `operation_id` | string | nein    | Eine `id` aus einem Suchergebnis, zum Beispiel `work-items.links.store`. |

- Mit `query` liefert es höchstens 12 Treffer als `{id, method, path, summary}`, dazu einen `hint` für den nächsten Schritt.
- Mit `operation_id` beschreibt es diese Operation: ihre Beschreibung, das nötige Recht, Pfadparameter, Query-Parameter, Filter, Sortierungen, Includes, Body-Felder, die Funktion, zu der sie gehört, und ein oder zwei Beispiele. Die ID funktioniert mit und ohne das Präfix `api.v2.`.
- Ohne Eingabe listet es jede Operations-ID auf, nach Bereich gruppiert.

Operationen, die Ihre Organisation nicht nutzen kann, fehlen: die von Bereichen, die Ihre Organisation nicht nutzt, Löschvorgänge, solange **Destruktive Aktionen erlauben** aus ist, und Datei-Uploads.

## api_read

Sendet ein `GET` an eine beliebige API-Operation.

| Eingabe | Typ    | Pflicht | Beschreibung                                                                                               |
| ------- | ------ | ------- | ---------------------------------------------------------------------------------------------------------- |
| `path`  | string | ja      | Der Pfad unterhalb von `/api/v2` mit ausgefüllten Platzhaltern, zum Beispiel `work-items/ACM-12/comments`. |
| `query` | object | nein    | Query-Parameter, zum Beispiel `{"filter": {"assignee_id": "me", "resolved": false}, "include": "labels"}`. |

### Pfade und Query

- Ein leerer Pfad listet die Ressourcen auf, die die API anbietet.
- Der Pfad darf mit `/api/v2` beginnen; das Präfix wird ignoriert.
- Der ganze Pfad hat höchstens 256 Zeichen. Seine Segmente bestehen nur aus Buchstaben, Ziffern, `-` und `_`, und jeder Platzhalter muss ausgefüllt sein.
- Pfade von Arbeitselementen akzeptieren Schlüssel, etwa `work-items/ACM-12`. Benutzerfilter akzeptieren `me`.
- Query-Objekte sind höchstens drei Ebenen tief verschachtelt, etwa `filter[due_date][gte]`, mit insgesamt höchstens 60 Parametern.
- Null-Werte werden weggelassen. Listen werden zu kommagetrennten Werten.

### Listen und Seiten

Listen kommen in Seiten zu 10 Einträgen in der Ansicht `summary` zurück, sofern der Aufruf nichts anderes verlangt. Für die nächste Seite wird `meta.page.next_cursor` der vorherigen Antwort als `cursor` übergeben. Ist `next_cursor` gleich `null`, gibt es keine weiteren Seiten.

Einige Listen akzeptieren auch eine Seitennummer. Ihr `meta.page` enthält immer `current_page` und `last_page`. Beide sind `null`, solange der Aufruf kein `page` sendet. Ein Aufruf mit `page` bekommt immer `next_cursor: null`. Die letzte Seite ist erreicht, wenn `current_page` gleich `last_page` ist.

## api_write

Sendet ein `POST`, `PATCH` oder `DELETE` an eine beliebige API-Operation.

| Eingabe   | Typ     | Pflicht | Beschreibung                                                                        |
| --------- | ------- | ------- | ----------------------------------------------------------------------------------- |
| `method`  | string  | ja      | `POST`, `PATCH` oder `DELETE`.                                                      |
| `path`    | string  | ja      | Der Pfad unterhalb von `/api/v2`, zum Beispiel `work-items/ACM-12/links`.           |
| `query`   | object  | nein    | Query-Parameter, zum Beispiel `{"view": "detail"}`.                                 |
| `body`    | object  | nein    | Der JSON-Body, zum Beispiel `{"link_type": "blocks", "target_work_item_id": 42}`.   |
| `confirm` | boolean | nein    | `true` bei einem Löschen oder Überschreiben, und erst nachdem Sie zugestimmt haben. |

Die Pfad- und Query-Regeln von `api_read` gelten auch hier. Der Body wird genau so geprüft, wie die REST-API ihn prüft: Ein Feld, das die Operation nicht annimmt, wird unter Nennung seines Namens abgelehnt, nie ignoriert.

Löschen braucht zweierlei: **Destruktive Aktionen erlauben** muss für Ihre Organisation eingeschaltet sein, und der Aufruf muss `confirm: true` mitsenden. Fehlt eines davon, wird nichts gelöscht. [Was als Löschen gilt](https://developers.plnnrly.com/de/docs/mcp/permissions-and-safety/#destructive) nennt die Operationen, die das betrifft. Bei `DELETE /projects/{project}` löscht die Query `{"force": true}` das Projekt endgültig, statt es so zu löschen, dass es sich wiederherstellen lässt.

Auch das Ersetzen des ganzen Texts eines Drive-Dokuments braucht `confirm: true`, weil dabei die Formatierung verloren geht und alles, was andere getippt haben, seit der Client das Dokument gelesen hat. Wer nur Text mit `{"mode": "append"}` im Body anfügt, braucht keine Bestätigung.

`api_write` lehnt diese Aufrufe ab, bevor irgendetwas ausgeführt wird:

| Ablehnung                                                      | Problemtyp            |
| -------------------------------------------------------------- | --------------------- |
| Ein Löschen, solange **Destruktive Aktionen erlauben** aus ist | `forbidden-by-policy` |
| Ein Löschen oder Überschreiben ohne `confirm: true`            | `validation-failed`   |
| Ein Datei-Upload                                               | `endpoint-not-found`  |
| Eine Methode, die die Operation nicht annimmt                  | `method-not-allowed`  |

Bei den ersten beiden wird der Datensatz vor der Ablehnung nicht gelesen. Eine Ablehnung verrät also nie, ob es den Datensatz gibt.

Schreibvorgänge über MCP sind nicht gegen Duplikate geschützt. Ein `Idempotency-Key` ist weder nötig, noch wird er verwendet. Ein Client, der nicht sicher ist, ob ein Schreibvorgang ausgeführt wurde, sollte deshalb erst lesen, bevor er es noch einmal versucht.

Hat die Anmeldung einer App auch Berechtigungen für die REST-API angefordert, ist die App über MCP ebenfalls an diese Berechtigungen gebunden. Berechtigungen aus einer Anmeldung umfassen nie das Löschen, deshalb kann eine solche App über MCP nicht löschen.

## get-current-user-tool

Gibt Ihr eigenes Profil zurück. Das Tool nimmt keine Eingabe an.

```json
{
  "id": 34,
  "name": "Jamie Doe",
  "email": "jamie@acme.example",
  "email_verified_at": "2026-02-03T09:15:00+00:00",
  "timezone": "Europe/Amsterdam",
  "locale": "en",
  "job_title": "Project manager",
  "date_employed": "2025-09-01",
  "roles": ["Project manager"],
  "created_at": "2025-08-28T14:02:11+00:00"
}
```

Die Zeitstempel enthalten einen Zeitzonen-Offset. `date_employed` ist ein Datum (`YYYY-MM-DD`). Felder ohne Wert sind `null`.

## Antworten

Eine erfolgreiche Antwort ist der Antwort-Body der API mit zwei Änderungen:

- Zuerst kommt ein Schlüssel `status` mit dem HTTP-Status, mit dem die API geantwortet hat, zum Beispiel `200` oder `201`.
- Jedes `links`-Objekt wird entfernt. Ein Client setzt eine Liste mit `meta.page.next_cursor` fort und ruft andere Datensätze über ihren Pfad auf.

Ein Löschen liefert keinen Body, deshalb gibt das Tool `{"status": 204}` zurück.

Eine Antwort darf etwa 30.000 Zeichen umfassen. Das Limit zählt Bytes, deshalb passt bei Text mit Umlauten, Akzenten oder Emoji etwas weniger hinein. Eine längere Antwort wird gekürzt, aber nie stillschweigend: `meta.mcp_truncated` sagt, was weggelassen wurde. Fehlen Zeilen einer Liste, wird `next_cursor` geleert, weil er sie sonst überspringen würde. Der `hint` erklärt, wie man lückenlos weiterblättert. So sieht das `meta`-Objekt einer gekürzten Liste aus:

```json
{
  "page": {
    "per_page": 10,
    "next_cursor": null,
    "prev_cursor": null,
    "total": null
  },
  "mcp_truncated": {
    "reason": "response_budget",
    "returned": 6,
    "omitted": 4,
    "hint": "Only the first 6 of 10 rows fit. Repeat this request with per_page=6 (and the same cursor, if any) to page through without gaps."
  }
}
```

Ist ein einzelner langer Text das Problem, listet `mcp_truncated` stattdessen die gekürzten Felder auf, jeweils mit ihrem `pointer`, der Zahl der behaltenen Zeichen (`kept`) und der ursprünglichen Länge (`length`).

## Fehler

Ein abgelehnter Aufruf kommt als Tool-Fehler zurück. Er enthält dasselbe [Fehlerdokument (problem+json, Englisch)](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/), das die REST-API liefert, mit demselben Status und Typ. Fragen Sie etwas ab, das Sie nicht sehen dürfen, kommt ein `404` zurück, genau wie über HTTP.

```json
{
  "type": "https://developers.plnnrly.com/api/v2/problems/forbidden-by-policy",
  "title": "Forbidden by policy",
  "status": 403,
  "detail": "This organisation does not allow AI clients to delete data. An administrator can turn on Allow destructive actions under Settings › Administration › MCP & API.",
  "instance": "/api/v2/work-items/ACM-12",
  "request_id": "01M4WVYY50K7T2B9QH3D6N8RXP"
}
```

Auf einen Pfad oder eine Query, mit denen die Tools nichts anfangen können, kommt [malformed-request](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/#malformed-request) zurück. Dessen `errors[].code` ist `invalid` (ein Pfad oder Wert, der nicht erlaubt ist), `too_many` (mehr als 60 Query-Parameter) oder `too_deep` (mehr als drei Ebenen verschachtelt).

## Limits

- Jeder Benutzer darf 60 MCP-Anfragen pro Minute senden. Gezählt wird jede Anfrage, die der Client an den Server sendet, auch die zum Aufbau der Verbindung und zum Auflisten der Tools, nicht nur Tool-Aufrufe. Ein Client über dem Limit bekommt `429`.
- Die Rate-Limits und Rate-Einheiten der REST-API gelten nicht für Aufrufe über MCP.
- Eine Antwort umfasst höchstens etwa 30.000 Zeichen.
- Der Client erneuert seine Anmeldung jede Stunde. Ein Client, der 30 Tage lang nicht benutzt wurde, muss sich erneut anmelden.

[Limits im Überblick (Englisch)](https://developers.plnnrly.com/en/docs/api/v2/guides/limits/) listet jedes Limit der REST-API auf.

## Was MCP nicht kann

- **Dateien hochladen.** Für einen Anhang oder eine Drive-Datei ist ein Byte-Upload nötig, den MCP-Clients nicht ausführen können. Nutzen Sie die REST-API mit einem API-Token; siehe [Dateien hoch- und herunterladen (Englisch)](https://developers.plnnrly.com/en/docs/api/v2/guides/uploads/).
- **Löschen, solange der Schalter aus ist.** Löschen funktioniert nur, solange Ihre Organisation destruktive Aktionen erlaubt.

## Siehe auch

- [Was Sie fragen können](https://developers.plnnrly.com/de/docs/mcp/examples/)
- [Rechte und Sicherheit](https://developers.plnnrly.com/de/docs/mcp/permissions-and-safety/)
- [Fehlerbehebung](https://developers.plnnrly.com/de/docs/mcp/troubleshooting/)
- [Fehler und Wiederholungen (Englisch)](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/)
