Infrastructure · We run it ourselves
An open protocol that lets an assistant call tools and read live data directly, instead of being handed an excerpt somebody pasted.
Most disappointment with an assistant is not a reasoning failure: it was asked about a system it cannot see and answered anyway. We do not just consume this protocol — we serve it, so a tenant can point their own assistant at their own operation. Everything difficult about that is in deciding what it may not touch.
01
The interesting question is not what a tenant's assistant may read but how the boundary is written. Our customer reader returns a decrypted Emirates ID, a passport and three licence numbers; it is simply absent from the catalogue, and where a reader does return a wide row the code names the fields that may pass rather than the ones that may not. That is not a style preference. The first version was a deny-list, stripped the two contact columns it knew about, and shipped a co-driver's passport number inside a JSONB bag nobody had looked at. A deny-list over a table somebody else will add a column to is a promise with an expiry date.
02
Permission is not re-implemented at the protocol edge. Every write goes through the same authorisation the web application uses, with the role the key was minted against, so a read-only key meets a clean refusal at the first write from the permission system itself. The alternative — a second allow-list living beside the tool catalogue — is a copy that drifts, and the drift is discovered by an assistant doing something nobody authorised.
03
Some capabilities are withheld on purpose and the rule is legible: nothing that burns a tax invoice number, charges a card, or sends a message to a real person. Those are irreversible or they reach a human being, and an assistant should not do them unsupervised. Writes are limited to reference data — the fleet and the price list.
04
Every list is capped before it leaves the server. Three readers scan a whole table and are admitted only because each is bounded by the tenant's own fleet or price list; the two that would scan an unbounded table are not in the catalogue at all. An assistant that can ask for everything will eventually ask for everything.
05
The server is built per request and closes over one tenant's context, so a handler assembled for one tenant cannot serve another's call. In a multi-tenant system that is the whole game, and it is worth the allocation.
06
The protocol SDK validates nothing by design — no origin check, no token verification — so both happen in front of it. Reading a specification for what it does not do is most of the security work in any new protocol, and it is the part that gets skipped while the capability is exciting.
07
The point of all of it is that the tenant's own assistant becomes the interface. They hand an address and a key to Claude or ChatGPT and ask about their fleet, their bookings and their money in their own words, without us building a reporting screen for every question somebody might have.
An entry that cannot point at something you can open, run or read does not compile. That is a property of the type, not a promise in a paragraph.
Invariant
MCP moves the access problem, it does not remove it. A server is an API key with a conversational front end, and the protocol has nothing to say about who may ask what — that stays with the application's own permission system, which is why ours defers to it rather than re-deciding at the edge. It is also not retrieval over documents: it answers from systems, not from prose, and a tenant wanting to ask questions of their contracts needs the other thing. And a capability this new moves fast: the specification is young, the SDKs ship without validation, and anyone standing one up in front of production data is doing security work the ecosystem has not finished doing for them.