Skip to content

MCP server

MCP (Model Context Protocol) is how AI clients are given tools. schakl. serves one at /mcp: every endpoint of the API is a tool there. You connect Claude Desktop, Claude Code or any other MCP client to your own installation and ask your question in plain language, without exporting anything first. What the AI may see and do is decided by the scopes on the key you hand it.

The server runs at https://<your-host>/mcp, on your organisation’s own address. There is no screen for it: you configure it on the client side, using a key from Instellingen → Mijn account (Settings → My account, the API-sleutels block) or from Instellingen → Service-accounts (Settings → Service accounts).

  1. Mint a key as described under REST API. Under Scopes, tick only what the AI may do — for asking questions that is usually read permissions only.

  2. Copy the key immediately. It is shown only once.

  3. Add the server to your client. For Claude Code:

    Terminal window
    claude mcp add --transport http schakl https://<your-host>/mcp \
    --header "Authorization: Bearer schakl_…"
  4. Any other client that speaks Streamable HTTP: point it at the same address with the header Authorization: Bearer schakl_… or X-API-Key: schakl_….

  5. Ask the client to list its tools. If nothing appears, check that you used your organisation’s own address — a key only exists on its own organisation’s hostname.

The tool list is derived straight from the API itself, so it never lags behind. Every endpoint under /api/v1 is a tool, named after the operation: list_companies, create_task, time_summary.

Only the modules your organisation has switched on have endpoints, so the tool list automatically follows which modules you use. Turn a module off and its tools disappear.

A few things are deliberately left out:

Not a toolWhy
Signing in and the first-run wizardsession handling, meaningless for a key
The instance operator’s administration surfacethat belongs to the instance owner, not the organisation
Import: inspecting a file and importing itthose need a file, plus the human judgement of mapping columns

The rest of import and export stays available: reading an entity’s columns and exporting data are both useful to an AI.

The full surface is ~620 tools, and that is the right default for a coding agent, which reads the list once. It is the wrong one for a chat client, which puts every tool in the model’s context on every turn and therefore budgets: ChatGPT allows 5,000 tokens for all tools together, and the full list is around 527,000. No amount of trimming closes that gap — at that count you have about 85 tokens per tool, which does not buy a name. Only fewer tools works.

So the same server answers on narrower URLs, and you paste whichever one fits the client:

URLWhat it offers
/mcpEverything. The default, and what a coding agent wants
/mcp/compactA curated read-only fourteen, small enough for a chat client’s ceiling
/mcp/<module>One module’s own endpoints, for example /mcp/google-ads or /mcp/invoicing
/mcp/<bundle>A named job spanning several modules, for example /mcp/infra or /mcp/growth

A module section is derived from that module’s own routes, so an endpoint added tomorrow is served tomorrow; a bundle names modules, never tools, which keeps it as self-maintaining as the sections it unions. A URL that names nothing is refused and tells you what does exist, rather than quietly falling back to all 620 — that would look like it worked and could not be spotted by reading.

A tool call travels exactly the same path as an ordinary request from a screen: hostname to organisation, row-level isolation in the database, then that endpoint’s own permission check. There is no second route to the data. A call the key holds no permission for simply comes back as an error on the tool.

Do watch what you tick: the tool surface includes writes, because it is the whole API. If you want the AI to read along only, give the key read permissions only. That is a choice you make when minting the key, not something the server enforces for you.

PermissionWhat it opensDefault
apikeys.personal.manageManage own API keysAdministrator, Member
apikeys.service_account.manageManage service accountsAdministrator

After that the key decides everything: each ticked scope is a permission from the same catalogue as Instellingen → Rollen (Settings → Roles). A personal key is additionally re-capped to its owner’s live permissions on every single request.

  • API keys are the only way in today. The full OAuth sign-in flow some MCP clients expect is not implemented, so such a client cannot connect yet.
  • The transport is Streamable HTTP with self-contained JSON responses. The older SSE transport is not offered.
  • 600 calls per minute per key. An AI that searches enthusiastically can run into that.
  • Intrekken (Revoke) in the key screen removes access immediately, with nothing to change on the client side.
  • The tool list comes entirely from the API description. Hand-written, smarter tools (such as “find this client”) do exist inside the in-app assistant, but are not part of this list.
  • To not serve the server at all, set SCHAKL_MCP_ENABLED=false on the server. That removes /mcp entirely.