All integrations

Automation & API Available

MCP (Model Context Protocol)

Point an AI client at your own instance and ask in plain language. Nothing gets exported and no second data path appears: the MCP server talks in-process to the same API the web app uses. A client that speaks OAuth does not even need a key, just the address.

What you need

  • Your own tenant hostname over HTTPS: the verified custom domain, or <slug>.<base domain>
  • A licence covering the mcp sku; without it the whole /mcp mount answers 402
  • SCHAKL_MCP_ENABLED must not be false (it is on by default)
  • For a key: the apikeys.personal.manage permission, or apikeys.service_account.manage for a service account. For OAuth: nothing extra, just an ordinary login
  • For an OAuth client with a fixed client id and secret: the settings.oauth.manage permission to create it
  • A client that speaks Streamable HTTP, for example Claude, Claude Code, Claude Desktop or ChatGPT

How to connect it

  1. 1 Check your licence under Instellingen → Licentie (Settings → Licence). MCP has its own sku (mcp); if it is not covered, /mcp answers 402 and there is nothing to connect.
  2. 2 Claude or ChatGPT as a connector: add https://<your-host>/mcp as a custom connector (ChatGPT: /mcp/compact). The client registers itself, you land on your own workspace's sign-in screen and then on Toegang toestaan (Allow access), where you choose between Alles wat ik zelf mag (everything I may do), Alleen lezen (read only) or Zelf kiezen (choose myself). No secret is copied anywhere.
  3. 3 A client with a key: open Instellingen → API en MCP, choose AI-assistent (MCP) under Wat koppel je? (what are you connecting), give the key a Naam, pick under Wat mag die doen? (what may it do; Alleen lezen by default) and the section under Welke tools. Leave Verloopt op empty for a key that never expires and press Sleutel aanmaken.
  4. 4 The screen prints the connection line for your client with the new key already in it, for Claude Code for example: claude mcp add --transport http schakl https://<your-host>/mcp --header "Authorization: Bearer schakl_…". The key is shown once.
  5. 5 A key that needs nobody's account: Instellingen → Service-accounts → Service-account toevoegen, then Nieuwe sleutel with its own scopes.
  6. 6 A tool that asks for a fixed client id and secret (an enterprise connector config, an automation tool): an admin creates one under OAuth-clients on the same screen, with one redirect URI per line. The secret is shown once.
  7. 7 Always use your own tenant hostname; a key presented on another organisation's hostname is simply not found.
  8. 8 Done with a connection: Ontkoppelen (disconnect) under Gekoppelde clients ends every session of that client, Intrekken (revoke) beside a key cuts access immediately.

The same gate as the web app

There is no second data path. A tool call goes in-process through the same handling as an HTTP request: the hostname resolves the organisation, row-level security is bound, and the key's permissions are resolved. A call that is not allowed surfaces the API's own 401 or 403 envelope as a tool error. The incoming key is never forwarded to any external service; the proxy only ever calls the API in-process.

OAuth mints a key, not a second kind of access

Clients that want a connector rather than a pasted secret, Claude and ChatGPT first among them, get a full OAuth 2.1 flow: self-registration, authorization code with PKCE, refresh, revocation and discovery. What that flow hands back is an ordinary API key belonging to the person who consented, so every rule that governs a personal key governs this too. And the authorization server signs nobody in: consent runs on the session the web app already holds, with your password and two-factor verification or with your organisation's SSO. An anonymous call to /mcp gets a 401 with the invitation to do OAuth, so a client discovers the server by being refused and a stranger cannot see which modules you run.

Read-first is a choice at mint time

The tool surface includes writes, because the whole API is in it. What a client may actually do lives in its key's permissions, and the screen starts on read only. A personal key and an OAuth connection are additionally capped by their owner's live permissions on every request, so demoting someone narrows their connections with them. Choose everything I may do or read only at consent and that is stored as a rule rather than as today's list: a module that arrives later is included by itself, without a chat client having to ask for consent again, and never wider than the person. Choose myself stays a fixed list, and the screen says so. A service-account key carries exactly the scopes you granted it.

  • Scopes come from the same permission catalogue as roles, including the own/any variant such as time.entry.read:own
  • The API's deny-by-default rule answers every call, an AI's included
  • Only enabled modules contribute routes, so the tool surface tracks what you actually run

An address per job

The full surface is some 620 tools. A coding assistant reads that list once; a chat client puts every tool in the model's context on every turn, and ChatGPT allows 5,000 tokens for all tools together. So the same server also answers on narrower addresses. A module section is derived from that module's routes, so whatever arrives tomorrow is in it tomorrow; a bundle names modules and never individual tools; and the compact fourteen is the only hand-picked list, because an outside ceiling forces it. A narrower list is not a smaller permission: what a key may do is decided when it is minted.

  • /mcp/compact: fourteen read-only tools, the right choice for ChatGPT
  • /mcp/agent: clients, contacts, projects, tasks, hours and contact moments
  • /mcp/infra: domains, websites, hosting, Cloudflare, OXXA, uptime and WordPress
  • /mcp/finance: invoices, subscriptions and payments
  • /mcp/growth: Google Ads, Analytics, Search Console, Tag Manager, marketing and reporting
  • /mcp/<module>: one module, for example /mcp/google-analytics, /mcp/google-search-console or /mcp/wordpress
  • An address that points at nothing is refused with the list of what does exist

Transport and pace

Streamable HTTP, stateless, with JSON responses: every JSON-RPC POST stands alone, so it works behind any load balancer and from plain curl. Each key is limited to 600 requests per minute, generous for automation and a firm ceiling under a leaked key. The Laatst gebruikt (Last used) column deliberately lags: it is updated out of band, so a tool call never waits on it.

Permissions

Grant these to the role that manages this integration (Settings → Roles). Admin-only by default, and never to the client role.

  • apikeys.personal.manage Manage your own API keys: mint and revoke them yourself. Granted to admin and member by default, because such a key can never exceed its owner.
  • apikeys.service_account.manage Manage service accounts: shared principals that belong to no one person. Admin only by default.
  • settings.oauth.manage Create OAuth clients with a fixed client id and secret, issue a new secret and revoke a client along with every key it ever issued. Admin only by default, because a standing credential onto MCP is the organisation's decision.

What it deliberately does not do

  • Not everything is a tool: /api/v1/auth, /api/v1/setup, /api/v1/instance, /api/v1/users and the import upload endpoints (/inspect and /import) are deliberately excluded. The column list and the export side of import and export stay reachable.
  • A route that takes a file as multipart is not a tool; where it matters there is a JSON twin, such as uploading an attachment as base64.
  • An OAuth connection made with choose myself keeps that day's list. A module switched on later only joins when you reconnect.
  • The older SSE transport is not offered, it is deprecated.
  • 600 requests per minute per key is a fixed ceiling, not a setting.
  • SCHAKL_MCP_ENABLED=false removes the whole /mcp surface; there is no per-tool switch.

Where to find it Instellingen → API en MCP (Settings → API and MCP): mint a key with the connection instructions attached, the connected OAuth clients, and for admins the OAuth clients with a client id and secret. Instellingen → Service-accounts for a key that outlives someone leaving. The endpoint itself is https://<your-host>/mcp.

Read the guide

More in this category

Other integrations