De MCP-server heeft geen tool per functie. Via drie algemene tools bereikt een AI-client elke operatie van de REST API (Engels), behalve bestanden uploaden, altijd namens jou en met jouw rechten. Een vierde tool geeft je eigen profiel terug. Krijgt de API er een functie bij, dan kunnen clients die direct gebruiken.
| Tool | Titel in clients | Wat hij doet |
|---|---|---|
search_api | Search the API | Zoekt API-operaties en beschrijft ze |
api_read | Read from the API | Stuurt een GET naar een API-operatie |
api_write | Write to the API | Stuurt een POST, PATCH of DELETE |
get-current-user-tool | Get current user | Geeft je profiel terug |
Drie tools lezen alleen. Write to the API is gemarkeerd als een tool die gegevens kan wijzigen, dus clients vragen standaard om je goedkeuring. Bij de meeste clients kun je hem toestaan voor één gesprek of voorgoed. Rechten en veiligheid legt uit wat een client mag.
Zo gebruikt een client de tools
Elke client krijgt van de server ook korte instructies. Die beschrijven drie stappen: zoek de operatie met search_api, lees wat die accepteert, en roep die dan aan met api_read of api_write. Ze vertellen de client ook dat:
- paden voor werkitems sleutels accepteren, zoals
ACM-12 - gebruikersfilters
meaccepteren - verwijderen
confirm: truenodig heeft, dat de client pas meestuurt nadat jij akkoord bent gegaan, en alleen werkt als je organisatie het toestaat - tekst aan een Drive-document wordt toegevoegd met
mode: append, omdat anders het hele document wordt vervangen
search_api
Zoekt API-operaties en beschrijft ze. Hij geeft alleen de eigen documentatie van de API terug, nooit gegevens uit je organisatie.
| Invoer | Type | Verplicht | Omschrijving |
|---|---|---|---|
query | string | nee | Trefwoorden, zoals link of log . |
operation_id | string | nee | Een id uit een zoekresultaat, zoals work-items.links.store. |
- Met
querygeeft hij maximaal 12 treffers terug als{id, method, path, summary}, plus eenhintvoor de volgende stap. - Met
operation_idbeschrijft hij die operatie: de beschrijving, het benodigde recht, padparameters, queryparameters, filters, sorteringen, includes, bodyvelden, de functie waar de operatie bij hoort, en een of twee voorbeelden. De id werkt met en zonder het voorvoegselapi.v2.. - Zonder invoer somt hij elke operatie-id op, gegroepeerd per onderdeel.
Operaties die je organisatie niet kan gebruiken, worden weggelaten: die van onderdelen die je organisatie niet gebruikt, verwijderoperaties zolang Destructieve acties toestaan uitstaat, en bestandsuploads.
api_read
Stuurt een GET naar elke API-operatie.
| Invoer | Type | Verplicht | Omschrijving |
|---|---|---|---|
path | string | ja | Het pad onder /api, met de placeholders ingevuld, zoals work-items. |
query | object | nee | Queryparameters, zoals {"filter": . |
Paden en query
- Een leeg pad somt de resources op die de API aanbiedt.
- Het pad mag met
/api/v2beginnen; dat voorvoegsel wordt genegeerd. - Het hele pad is maximaal 256 tekens. De segmenten bevatten alleen letters, cijfers,
-en_, en elke placeholder moet zijn ingevuld. - Paden voor werkitems accepteren sleutels, zoals
work-items/ACM-12. Gebruikersfilters accepterenme. - Queryobjecten zijn maximaal drie niveaus diep, zoals
filter[due_date][gte], met in totaal maximaal 60 parameters. - Null-waarden worden weggelaten. Lijsten worden omgezet in kommagescheiden waarden.
Lijsten en pagina's
Lijsten komen terug in pagina's van 10 in de weergave summary, tenzij de aanroep om iets anders vraagt. Voor de volgende pagina geef je de meta.page.next_cursor van het vorige antwoord mee als cursor. Is next_cursor gelijk aan null, dan zijn er geen pagina's meer.
Sommige lijsten accepteren ook een paginanummer. Hun meta.page heeft altijd current_page en last_page, die null zijn tenzij de aanroep page meestuurt. Een aanroep met page krijgt altijd next_cursor: null. De laatste pagina is die waarop current_page gelijk is aan last_page.
api_write
Stuurt een POST, PATCH of DELETE naar elke API-operatie.
| Invoer | Type | Verplicht | Omschrijving |
|---|---|---|---|
method | string | ja | POST, PATCH of DELETE. |
path | string | ja | Het pad onder /api, zoals work-items. |
query | object | nee | Queryparameters, zoals {"view": . |
body | object | nee | De JSON-body, zoals {"link_type": . |
confirm | boolean | nee | true bij een verwijdering of een overschrijving, en alleen nadat jij ermee akkoord bent gegaan. |
De regels voor pad en query van api_read gelden hier ook. De body wordt precies zo gecontroleerd als de REST API dat doet: een veld dat de operatie niet accepteert, wordt geweigerd met vermelding van de naam, en nooit genegeerd.
Verwijderen vraagt twee dingen: Destructieve acties toestaan moet aanstaan voor je organisatie, en de aanroep moet confirm: true meesturen. Ontbreekt een van beide, dan wordt er niets verwijderd. Wat telt als verwijderen somt de operaties op waarvoor dit geldt. Bij DELETE /projects/{project} verwijdert de query {"force": true} het project definitief, in plaats van een verwijdering die je kunt terugdraaien.
De hele tekst van een Drive-document vervangen vraagt ook confirm: true. Daarmee verdwijnen namelijk de opmaak en alles wat anderen hebben getypt sinds de client het document las. Tekst toevoegen met {"mode": "append"} in de body vraagt geen bevestiging.
api_write weigert deze aanroepen voordat er iets gebeurt:
| Weigering | Probleemtype |
|---|---|
| Een verwijdering terwijl Destructieve acties toestaan uitstaat | forbidden-by-policy |
Een verwijdering of overschrijving zonder confirm: | validation-failed |
| Een bestandsupload | endpoint-not-found |
| Een methode die de operatie niet accepteert | method-not-allowed |
Bij de eerste twee wordt het record niet gelezen voordat de aanroep wordt geweigerd, dus een weigering verraadt nooit of het record bestaat.
Schrijfacties via MCP zijn niet beschermd tegen dubbele uitvoering. Een Idempotency-Key is niet nodig en wordt niet gebruikt. Weet een client niet zeker of een schrijfactie is gelukt, dan moet hij eerst lezen voordat hij het opnieuw probeert.
Vroeg een app bij het inloggen ook om tokenrechten voor de REST API, dan is hij via MCP ook aan die tokenrechten gebonden. Tokenrechten die bij het inloggen worden gevraagd, omvatten nooit verwijderen, dus zo'n app kan via MCP niets verwijderen.
get-current-user-tool
Geeft je eigen profiel terug. Deze tool heeft geen invoer.
{
"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"
}
De tijdstempels vermelden de tijdzone als afwijking van UTC. date_employed is een datum (YYYY-MM-DD). Velden zonder waarde zijn null.
Antwoorden
Een geslaagd antwoord is de body die de API zelf teruggeeft, met twee wijzigingen:
- Vooraan staat een sleutel
status, met de HTTP-status waarmee de API antwoordde, zoals200of201. - Elk
links-object is verwijderd. Een client bladert verder in een lijst metmeta.page.next_cursor, en roept andere records aan via hun pad.
Een verwijdering antwoordt zonder body, dus de tool geeft {"status": 204} terug.
Een antwoord mag ongeveer 30.000 tekens bevatten. De limiet telt bytes, dus tekst met accenten of emoji past er iets minder in. Een langer antwoord wordt ingekort, nooit ongemerkt: meta.mcp_truncated zegt wat er is weggelaten. Zijn er rijen uit een lijst weggelaten, dan wordt next_cursor leeggemaakt, omdat je die rijen anders zou overslaan. De hint zegt hoe je zonder gaten verder bladert. Dit is het meta-object van een ingekorte lijst:
{
"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."
}
}
Is één lange tekst het probleem, dan somt mcp_truncated in plaats daarvan de ingekorte velden op, elk met zijn pointer, het aantal behouden tekens (kept) en de oorspronkelijke lengte (length).
Fouten
Een geweigerde aanroep komt terug als toolfout. Die bevat hetzelfde foutdocument als de REST API teruggeeft, met dezelfde status en hetzelfde type; zie Fouten en opnieuw proberen (Engels). Iets wat je niet mag zien, geeft 404, precies zoals via HTTP.
{
"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"
}
Een pad of query die de tools niet kunnen gebruiken, geeft malformed-request. De errors[].code daarvan is invalid (een pad of waarde die niet is toegestaan), too_many (meer dan 60 queryparameters) of too_deep (meer dan drie niveaus diep).
Limieten
- Elke gebruiker mag 60 MCP-verzoeken per minuut sturen. Dat geldt voor elk verzoek dat de client naar de server stuurt, ook voor de verzoeken die de verbinding opzetten en de tools opvragen, niet alleen voor toolaanroepen. Een client boven de limiet krijgt
429. - De eigen rate limits en rate units van de REST API gelden niet voor aanroepen via MCP.
- Een antwoord bevat maximaal ongeveer 30.000 tekens.
- De client vernieuwt zijn inlog elk uur. Een client die 30 dagen niet is gebruikt, moet opnieuw inloggen.
Limieten in één oogopslag (Engels) somt elke limiet van de REST API op.
Wat MCP niet kan
- Bestanden uploaden. Een bijlage of Drive-bestand toevoegen vraagt een upload van bytes, en die kunnen MCP-clients niet doen. Gebruik de REST API met een API-token; zie Bestanden uploaden en downloaden (Engels).
- Verwijderen zolang de schakelaar uitstaat. Verwijderen werkt alleen zolang je organisatie destructieve acties toestaat.