Ga naar inhoud

MCP-server

MCP (Model Context Protocol) is de manier waarop AI-clients gereedschap krijgen. schakl. biedt zo’n server aan op /mcp: elk eindpunt van de API is er een tool. Je koppelt Claude Desktop, Claude Code of een andere MCP-client aan je eigen installatie en stelt je vraag in gewone taal, zonder eerst iets te exporteren. Wat de AI mag zien en doen, bepaal je met de scopes van de sleutel die je hem geeft.

De server draait op https://<jouw-adres>/mcp, op het eigen adres van je organisatie. Het scherm erbij is Instellingen → API en MCP: daar maak je een sleutel aan en krijg je de koppelregel voor je client er meteen bij, staan de clients die je via OAuth hebt gekoppeld, en maakt een beheerder OAuth-clients met een vaste client-ID en secret. Sleutels die bij niemand horen staan onder Instellingen → Service-accounts.

Claude (als eigen connector, in de browser of in Claude Desktop) en ChatGPT spreken OAuth 2.1, en hebben dan alleen het adres nodig.

  1. Voeg in je client een eigen connector toe met het adres https://<jouw-adres>/mcp. Voor ChatGPT is dat https://<jouw-adres>/mcp/compact: de volledige lijst past niet in zijn budget.
  2. De client registreert zichzelf en stuurt je naar het inlogscherm van je eigen werkruimte. Je logt in zoals altijd, met tweestapsverificatie of de SSO van je organisatie.
  3. Op Toegang toestaan kies je wat de client mag:
    • Alles wat ik zelf mag: lezen en wijzigen, in elke module waar je toegang toe hebt;
    • Alleen lezen: alles wat je mag lezen, zonder ooit iets te wijzigen;
    • Zelf kiezen: een lijst die je zelf aanvinkt, gegroepeerd per module.
  4. Druk op Toestaan. Er wordt nergens een geheim gekopieerd.

Wat die flow oplevert is een gewone persoonlijke API-sleutel, geen tweede soort toegang: elk verzoek wordt afgetopt op jouw actuele rechten en je klantselectie. De eerste twee keuzes worden bewaard als regel, niet als de lijst van vandaag: gaat er later een module aan, dan hoort die er vanzelf bij, want een chatclient vraagt nooit opnieuw om toestemming. Zelf kiezen blijft een vaste lijst; een nieuwe module komt er pas bij als je opnieuw koppelt.

Je ziet je koppelingen onder Gekoppelde clients op Instellingen → API en MCP. Ontkoppelen beëindigt elke sessie van die client, en die kan zichzelf niet vernieuwen.

Een client die om een client-ID en secret vraagt

Section titled “Een client die om een client-ID en secret vraagt”

Claude heeft geen client-ID nodig. Tools die zichzelf niet registreren, zoals een zakelijke connectorconfiguratie of een automatiseringstool, vragen wel om een vaste client-ID en secret. Een beheerder met settings.oauth.manage maakt die aan onder OAuth-clients op hetzelfde scherm: een naam en één redirect-URI per regel. Het secret wordt precies één keer getoond. Dezelfde kaart toont ook de clients die zichzelf registreerden, apart gemarkeerd, met Nieuw secret (alleen voor clients die hier zijn aangemaakt) en Intrekken, dat de client uitschakelt met elke sleutel die hij ooit uitgaf, van wie dan ook.

  1. Open Instellingen → API en MCP. Kies bij Wat koppel je? voor AI-assistent (MCP).

  2. Geef de sleutel een Naam en kies bij Wat mag die doen?: Alleen lezen (de standaard, en meestal genoeg), Lezen en schrijven, of Kies per recht.

  3. Kies bij Welke tools de sectie die bij je client past (zie hieronder). Laat Verloopt op leeg voor een sleutel die nooit verloopt en druk op Sleutel aanmaken.

  4. Het scherm drukt de koppelregel af met de sleutel er al in. Voor Claude Code:

    Terminal window
    claude mcp add --transport http schakl https://<jouw-adres>/mcp \
    --header "Authorization: Bearer schakl_…"

    Kopieer hem meteen: de sleutel wordt maar één keer getoond.

  5. Een andere client die Streamable HTTP spreekt, wijs je naar hetzelfde adres met de header Authorization: Bearer schakl_… of X-API-Key: schakl_….

  6. Vraag de client de tools op te halen. Verschijnt er niets, controleer dan of je het eigen adres van je organisatie gebruikt: een sleutel bestaat alleen op de hostnaam van zijn eigen organisatie.

De toollijst wordt rechtstreeks afgeleid van de API zelf, dus hij loopt nooit achter. Elk eindpunt onder /api/v1 is een tool, met de korte naam van de bewerking: list_companies, create_task, time_summary.

Alleen de modules die jouw organisatie aan heeft staan hebben eindpunten, dus de toollijst volgt vanzelf welke modules je gebruikt. Zet je een module uit, dan verdwijnt zijn gereedschap.

Een paar dingen doen bewust niet mee:

Niet als toolWaarom
Inloggen en de eerste-start-wizardsessieafhandeling, zinloos voor een sleutel
Het beheerderscherm van de instantiedat is de instantie-eigenaar, niet de organisatie
Import: bestand inspecteren en importerendaar hoort een bestand en menselijk kolommen-koppelen bij

De rest van import en export blijft wel beschikbaar: kolommen opvragen en gegevens exporteren zijn allebei bruikbaar voor een AI.

Het volledige oppervlak telt zo’n 620 tools, en dat is de juiste standaard voor een programmeerassistent, die de lijst één keer leest. Het is de verkeerde voor een chatclient, die elke tool bij elke beurt in de context van het model zet en daar dus een budget voor heeft: ChatGPT staat 5.000 tokens toe voor alle tools samen, en de volledige lijst zit rond de 527.000. Snoeien lost dat niet op: bij dat aantal houd je zo’n 85 tokens per tool over, en daar past nog geen naam in. Alleen minder tools werkt.

Dezelfde server antwoordt daarom ook op smallere adressen, en je plakt het adres dat bij je client past:

AdresWat het aanbiedt
/mcpAlles. De standaard, en wat een programmeerassistent wil
/mcp/compactEen samengestelde, alleen-lezen veertien, klein genoeg voor het plafond van een chatclient
/mcp/<module>De endpoints van één module, bijvoorbeeld /mcp/google-ads of /mcp/invoicing
/mcp/<bundel>Een benoemde klus over meerdere modules heen (zie hieronder)
BundelModules
/mcp/agentKlanten, contactpersonen, projecten, taken, uren, contactmomenten
/mcp/infraDomeinen, websites, hosting, Cloudflare, OXXA, uptime, WordPress
/mcp/financeFacturatie, abonnementen, Mollie
/mcp/growthGoogle Ads, Google Analytics, Search Console, Tag Manager, marketing, rapportage

Google Analytics, Search Console en WordPress hebben daarnaast hun eigen sectie (/mcp/google-analytics, /mcp/google-search-console, /mcp/wordpress): een agent die de Analytics van een klant moet doorlopen wil zeventien tools, niet de honderd van de hele bundel.

Een modulesectie wordt afgeleid uit de routes van die module zelf, dus een endpoint dat er morgen bij komt wordt morgen aangeboden; een bundel noemt modules en nooit tools, waardoor hij zichzelf net zo goed bijhoudt als de secties die hij samenvoegt. Een adres dat nergens naar verwijst wordt geweigerd, met erbij wat er wél bestaat, in plaats van stilletjes terug te vallen op alle 620: dat zou eruitzien alsof het werkte en met lezen niet te ontdekken zijn.

Een toolaanroep loopt precies dezelfde weg als een gewoon verzoek uit het scherm: hostnaam naar organisatie, afscherming op databaseniveau, en daarna de rechtencontrole van dat eindpunt. Er is geen tweede route naar de gegevens. Een aanroep waar de sleutel geen recht voor heeft komt gewoon terug als een foutmelding bij de tool.

Let wel op wat je aanvinkt: het gereedschap bevat ook schrijfacties, want het is de hele API. Wil je dat de AI alleen kan meelezen, geef de sleutel dan uitsluitend leesrechten. Dat is een keuze bij het aanmaken van de sleutel, niet iets wat de server voor je afdwingt.

RechtWat het opentStandaard
apikeys.personal.manageEigen API-sleutels beherenBeheerder, Medewerker
apikeys.service_account.manageServiceaccounts beherenBeheerder
settings.oauth.manageOAuth-clients met een vaste client-ID en secret beherenBeheerder

Daarna bepaalt de sleutel zelf alles: elke aangevinkte scope is een recht uit dezelfde catalogus als Instellingen → Rollen. Een persoonlijke sleutel wordt daarbovenop elk verzoek opnieuw begrensd door de actuele rechten van de eigenaar.

  • Een anonieme aanroep krijgt een 401, met de uitnodiging om OAuth te doen. Zo vindt een client de server door geweigerd te worden, en ziet een onbekende niet welke modules je draait.
  • Het transport is Streamable HTTP met losstaande JSON-antwoorden. De oudere SSE-variant wordt niet aangeboden.
  • 600 aanroepen per minuut per sleutel. Een AI die enthousiast doorzoekt kan daar tegenaan lopen.
  • Intrekken in het sleutelscherm haalt de toegang er per direct af, zonder dat er aan de kant van de client iets hoeft te gebeuren.
  • De toollijst komt volledig uit de API-beschrijving. Handgeschreven, slimmere tools (zoals “zoek deze klant” of de prestaties van een klant met de vergelijking al uitgerekend) bestaan wel binnen de assistent in de app, maar zitten niet in deze lijst.
  • Een route die een bestand als multipart neemt is geen tool. Waar dat ertoe doet is er een JSON-tweeling, zoals een bijlage uploaden als base64.
  • Wil je de server helemaal niet aanbieden, dan zet je op de server SCHAKL_MCP_ENABLED=false. Daarmee verdwijnt /mcp volledig.