# Outils

Les quatre outils du serveur MCP de plnnrly, ce que chacun accepte et renvoie, et les limites qui s'appliquent.

Le serveur MCP n'a pas un outil par fonctionnalité. Grâce à trois outils généraux, un client IA accède à toutes les opérations de l'[API REST (en anglais)](https://developers.plnnrly.com/en/docs/api/v2/), sauf l'envoi de fichiers, toujours en votre nom et avec vos droits. Un quatrième outil renvoie votre propre profil. Quand l'API s'enrichit d'une fonctionnalité, les clients peuvent l'utiliser tout de suite.

| Outil                   | Titre affiché par les clients | Ce qu'il fait                                |
| ----------------------- | ----------------------------- | -------------------------------------------- |
| `search_api`            | Search the API                | Trouve des opérations de l'API et les décrit |
| `api_read`              | Read from the API             | Envoie un `GET` à une opération de l'API     |
| `api_write`             | Write to the API              | Envoie un `POST`, un `PATCH` ou un `DELETE`  |
| `get-current-user-tool` | Get current user              | Renvoie votre profil                         |

Trois outils ne font que lire. **Write to the API** est signalé comme un outil qui peut modifier des données : les clients vous demandent donc de l'approuver par défaut. La plupart des clients vous laissent l'autoriser pour une conversation ou de façon permanente. La page [Droits et sécurité](https://developers.plnnrly.com/fr/docs/mcp/permissions-and-safety/) explique ce qu'un client a le droit de faire.

## Comment un client utilise les outils

Chaque client reçoit aussi du serveur une courte série d'instructions. Elles décrivent trois étapes : trouver l'opération avec `search_api`, lire ce qu'elle accepte, puis l'appeler avec `api_read` ou `api_write`. Elles indiquent aussi au client que :

- les chemins des éléments de travail acceptent des clés comme `ACM-12`
- les filtres sur les utilisateurs acceptent `me`
- supprimer demande `confirm: true`, envoyé seulement après votre accord, et ne fonctionne que si votre organisation l'autorise
- du texte s'ajoute à un document Drive avec `mode: append`, car sans cette option le document entier est remplacé

## search_api

Trouve des opérations de l'API et les décrit. Il ne renvoie que la documentation de l'API elle-même, jamais de données de votre organisation.

| Paramètre      | Type   | Obligatoire | Description                                                              |
| -------------- | ------ | ----------- | ------------------------------------------------------------------------ |
| `query`        | string | non         | Des mots-clés, comme `link work items` ou `log time`.                    |
| `operation_id` | string | non         | Un `id` issu d'un résultat de recherche, comme `work-items.links.store`. |

- Avec `query`, il renvoie au plus 12 correspondances sous la forme `{id, method, path, summary}`, plus un `hint` pour l'étape suivante.
- Avec `operation_id`, il décrit cette opération : sa description, le droit nécessaire, les paramètres de chemin, les paramètres de requête, les filtres, les tris, les inclusions, les champs du corps, la fonctionnalité dont elle fait partie, et un ou deux exemples. L'identifiant fonctionne avec ou sans le préfixe `api.v2.`.
- Sans aucun des deux, il liste tous les identifiants d'opération, regroupés par partie de plnnrly.

Les opérations que votre organisation ne peut pas utiliser sont laissées de côté : celles des parties de plnnrly que votre organisation n'utilise pas, les suppressions tant que **Autoriser les actions destructives** est désactivé, et l'envoi de fichiers.

## api_read

Envoie un `GET` à n'importe quelle opération de l'API.

| Paramètre | Type   | Obligatoire | Description                                                                                                   |
| --------- | ------ | ----------- | ------------------------------------------------------------------------------------------------------------- |
| `path`    | string | oui         | Le chemin sous `/api/v2`, avec ses variables remplies, comme `work-items/ACM-12/comments`.                    |
| `query`   | object | non         | Les paramètres de requête, comme `{"filter": {"assignee_id": "me", "resolved": false}, "include": "labels"}`. |

### Chemins et paramètres de requête

- Un chemin vide liste les ressources que propose l'API.
- Le chemin peut commencer par `/api/v2` ; ce préfixe est ignoré.
- Le chemin complet fait au plus 256 caractères. Ses segments n'utilisent que des lettres, des chiffres, `-` et `_`, et chaque variable doit être remplie.
- Les chemins des éléments de travail acceptent des clés, comme `work-items/ACM-12`. Les filtres sur les utilisateurs acceptent `me`.
- Les objets de requête s'imbriquent sur trois niveaux au plus, comme `filter[due_date][gte]`, avec 60 paramètres au plus en tout.
- Les valeurs nulles sont omises. Les listes deviennent des valeurs séparées par des virgules.

### Listes et pagination

Les listes sont renvoyées par pages de 10 dans la vue résumée, sauf si l'appel demande autre chose. Pour obtenir la page suivante, passez le `meta.page.next_cursor` de la réponse précédente comme `cursor`. Quand `next_cursor` vaut `null`, il n'y a plus de page.

Certaines listes acceptent aussi un numéro de page. Leur `meta.page` contient toujours `current_page` et `last_page`, qui valent `null` sauf si l'appel envoie `page`. Un appel qui envoie `page` reçoit toujours `next_cursor: null`. La dernière page est celle où `current_page` atteint `last_page`.

## api_write

Envoie un `POST`, un `PATCH` ou un `DELETE` à n'importe quelle opération de l'API.

| Paramètre | Type    | Obligatoire | Description                                                                    |
| --------- | ------- | ----------- | ------------------------------------------------------------------------------ |
| `method`  | string  | oui         | `POST`, `PATCH` ou `DELETE`.                                                   |
| `path`    | string  | oui         | Le chemin sous `/api/v2`, comme `work-items/ACM-12/links`.                     |
| `query`   | object  | non         | Les paramètres de requête, comme `{"view": "detail"}`.                         |
| `body`    | object  | non         | Le corps JSON, comme `{"link_type": "blocks", "target_work_item_id": 42}`.     |
| `confirm` | boolean | non         | `true` pour une suppression ou un écrasement, et seulement après votre accord. |

Les règles de chemin et de paramètres de requête de `api_read` s'appliquent ici aussi. Le corps est vérifié exactement comme l'API REST le vérifie : un champ que l'opération n'accepte pas est refusé nommément, jamais ignoré.

Une suppression exige deux conditions : **Autoriser les actions destructives** doit être activé pour votre organisation, et l'appel doit inclure `confirm: true`. S'il en manque une, rien n'est supprimé. [Ce qui compte comme une suppression](https://developers.plnnrly.com/fr/docs/mcp/permissions-and-safety/#destructive) liste les opérations concernées. Sur `DELETE /projects/{project}`, le paramètre de requête `{"force": true}` supprime le projet définitivement, au lieu d'une suppression réversible.

Remplacer tout le texte d'un document Drive demande aussi `confirm: true`, car cela efface la mise en forme et tout ce que d'autres ont tapé depuis que le client a lu le document. Ajouter du texte avec `{"mode": "append"}` dans le corps ne demande aucune confirmation.

`api_write` refuse ces appels avant que quoi que ce soit ne s'exécute :

| Refus                                                                         | Type d'erreur         |
| ----------------------------------------------------------------------------- | --------------------- |
| Une suppression tant que **Autoriser les actions destructives** est désactivé | `forbidden-by-policy` |
| Une suppression ou un écrasement sans `confirm: true`                         | `validation-failed`   |
| Un envoi de fichier                                                           | `endpoint-not-found`  |
| Une méthode que l'opération n'accepte pas                                     | `method-not-allowed`  |

Aucun des deux premiers refus ne lit l'enregistrement avant de refuser : un refus n'indique donc jamais si l'enregistrement existe.

Les écritures via MCP ne sont pas protégées contre les doublons. Un en-tête `Idempotency-Key` n'est ni nécessaire ni utilisé : un client qui ne sait pas si une écriture a abouti doit relire les données avant de réessayer.

Si l'identification d'une application demandait aussi des autorisations sur l'API REST, l'application reste limitée à ces autorisations via MCP également. Les autorisations obtenues par identification n'incluent jamais la suppression : une telle application ne peut donc pas supprimer via MCP.

## get-current-user-tool

Renvoie votre propre profil. Il ne prend aucun paramètre.

```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"
}
```

Les horodatages incluent un décalage de fuseau horaire. `date_employed` est une date (`YYYY-MM-DD`). Les champs sans valeur valent `null`.

## Réponses

Une réponse réussie est le corps de réponse de l'API elle-même, avec deux changements :

- Une clé `status` vient en premier, avec le statut HTTP que l'API a renvoyé, comme `200` ou `201`.
- Chaque objet `links` est retiré. Un client poursuit une liste avec `meta.page.next_cursor`, et appelle les autres enregistrements par leur chemin.

La réponse à une suppression n'a pas de corps : l'outil renvoie alors `{"status": 204}`.

Une réponse peut contenir environ 30 000 caractères. La limite se mesure en octets : une réponse qui contient des accents ou des emojis compte donc un peu moins de caractères. Une réponse plus longue est raccourcie, jamais sans le signaler : `meta.mcp_truncated` indique ce qui a été coupé. Quand des lignes ont été retirées d'une liste, `next_cursor` est vidé, car le suivre ferait sauter ces lignes. Le `hint` explique comment poursuivre la pagination sans rien manquer. Voici l'objet `meta` d'une liste raccourcie :

```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."
  }
}
```

Quand c'est un seul long texte qui pose problème, `mcp_truncated` liste plutôt les champs raccourcis, chacun avec son `pointer`, le nombre de caractères conservés (`kept`) et la longueur d'origine (`length`).

## Erreurs

Un appel refusé revient sous forme d'erreur d'outil. Elle contient le même document d'erreur (problem+json) que l'API REST, avec le même statut et le même type ; le guide [Erreurs et nouvelles tentatives (en anglais)](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/) décrit chaque type. Ce que vous n'avez pas le droit de voir renvoie `404`, exactement comme via 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"
}
```

Un chemin ou un paramètre de requête que les outils ne peuvent pas utiliser renvoie l'erreur [malformed-request](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/#malformed-request). Son `errors[].code` vaut `invalid` (un chemin ou une valeur non autorisés), `too_many` (plus de 60 paramètres de requête) ou `too_deep` (plus de trois niveaux d'imbrication).

## Limites

- Chaque utilisateur peut envoyer 60 requêtes MCP par minute. Toutes les requêtes que le client envoie au serveur comptent, y compris celles qui établissent la connexion et listent les outils, pas seulement les appels d'outils. Un client qui dépasse la limite reçoit `429`.
- Les limites de débit et les unités de débit propres à l'API REST ne s'appliquent pas aux appels passés via MCP.
- Une réponse contient au plus environ 30 000 caractères.
- Le client renouvelle son identification toutes les heures. Un client inutilisé pendant 30 jours doit s'identifier de nouveau.

La page [Limites en un coup d'œil (en anglais)](https://developers.plnnrly.com/en/docs/api/v2/guides/limits/) liste toutes les limites de l'API REST.

## Ce que MCP ne permet pas

- **Envoyer des fichiers.** Ajouter une pièce jointe ou un fichier Drive demande un envoi d'octets que les clients MCP ne savent pas faire. Utilisez l'API REST avec un token API ; voir [Fichiers : envoi et téléchargement (en anglais)](https://developers.plnnrly.com/en/docs/api/v2/guides/uploads/).
- **Supprimer tant que le réglage est désactivé.** Les suppressions ne fonctionnent que si votre organisation autorise les actions destructives.

## Voir aussi

- [Ce que vous pouvez demander](https://developers.plnnrly.com/fr/docs/mcp/examples/)
- [Droits et sécurité](https://developers.plnnrly.com/fr/docs/mcp/permissions-and-safety/)
- [Dépannage](https://developers.plnnrly.com/fr/docs/mcp/troubleshooting/)
- [Erreurs et nouvelles tentatives (en anglais)](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/)
