What a governed MCP server looks like in production
We operate five of them across four industries, carrying more than 200 tools between them. This is what actually stops an assistant doing damage, written from systems that run rather than from a demo.
Everyone can demonstrate an assistant reading a database. The engineering is all in what it is not allowed to do.
Six controls, and one question that separates a demo from a system.
Connecting an assistant to a business system is a weekend's work. Connecting one to a business system that a finance team will still trust in month six is a different exercise, and almost all of it is spent on refusals rather than capabilities.
We run five production Model Context Protocol servers across fund compliance, legal practice, packaging distribution and planning. They carry more than 200 tools between them. What follows is what those deployments have in common, and it is deliberately unglamorous.
The question
When somebody demonstrates an AI assistant over company data, there is one question worth asking, and it is not about the model.
Everything below exists to make that second answer possible.
The six controls
Named tools, never query access
The server publishes a fixed list of named actions. There is no tool that accepts arbitrary SQL, and adding one would undo every other control on this list. This is the difference people find hardest to accept, because query access demos beautifully. It also means the assistant cannot be talked into a query nobody reviewed, since the query does not exist as an option.
Read-only by default, writes as a minority
Most tools on a well-shaped server only read. On our fund-compliance server, 58 of 67 tools are read-only and 9 can write. Treating writes as the exception rather than the default is what keeps the blast radius of a misunderstanding small.
Two-step writes with a confirm token
A write tool called normally does not write. It returns a preview of exactly what would change, plus a token computed from that payload. Committing requires calling again with the token. Because the token is derived from the content, an approval cannot be replayed against altered content, and a person has seen the change before it happened.
The user's own permissions, not the server's
Sign-in is fail-closed and federated to the organisation's own identity provider, and every call runs as the real person. Somebody who can see two of five group companies in the application sees two through the assistant. A server with its own god-mode service account is a permissions system that has been quietly turned off.
Names in, names out
Internal record identifiers never reach the model, through a single scrub point rather than tool by tool. Tools take and return names. This is partly hygiene and partly practical: an assistant that has never seen an id cannot invent a plausible one and act on it.
Every call logged against the real user
Not sampled, not aggregated. Who asked, which tool, what arguments, what came back. This is the control that makes the other five auditable rather than merely claimed, and it is the one an internal-audit function will ask for first.
What "the same numbers" actually requires
The most common failure is subtler than a permissions breach: the assistant and the dashboard disagree, somebody notices, and nobody trusts either again.
The fix is architectural rather than careful. The tools call the same application services the screens call, rather than writing their own queries against the same tables. Reimplementing "revenue" in a tool is how you end up with two definitions of revenue, and the second one is always the one in the room when it matters.
The corollary is that data freshness has to be told, not hidden. Where one country reads live and another syncs daily, an answer that quietly averages the two is worse than an answer that says which is which.
What we run
Tool counts are a poor measure of quality, and we publish ours only because the shape of the split is the interesting part: the read-to-write ratio, and how few surfaces need writes at all.
| Surface | Tools | Notes |
|---|---|---|
| Fund compliance | 67 | 58 read-only, 9 guarded writes |
| Legal practice | ~97 | 38 guarded two-step writes |
| Group BI, packaging | ~34 | Read-only |
| Legal public data | 19 | Read-only |
| Planning models | 15 | Gated write-back |
Five servers, four industries, 200+ tools. Counts verified in source; two are approximate because those surfaces are still growing.
The part that is genuinely hard
None of the six controls above is difficult to implement. What is difficult is deciding what the tools should be, because a tool surface is a set of decisions about what questions the business is allowed to ask cheaply.
Ninety-seven tools is not a boast, it is the consequence of a practice manager wanting ninety-seven different things and each one deserving a named, reviewable action rather than a clever prompt. That design work is most of the project, and it is the part that cannot be bought.
Try it rather than trust it
We run a public demo server over an invented distributor. It is read-only apart from one write-shaped tool that exists purely to show the preview-and-confirm gate, and it has no arbitrary-query tool because that is the rule we are describing. Connect an assistant and try to make it misbehave.
If you would rather talk about your own systems, we will tell you which of your questions are cheap to answer this way and which are not worth the governance they would need.