The Model Context Protocol solved a real problem and created a quieter one. MCP is the open standard that lets an AI agent discover and call tools — a database query, a payment endpoint, a batch-release function — through a uniform interface, so you stop hand-wiring every integration. The agent connects to an MCP server, the server advertises its tools, and the agent calls whichever it needs.
That last clause is the problem. Whichever it needs. Once an agent can reach a server, it can call anything that server exposes. Authority becomes a function of network reach rather than deliberate grant. In a regulated environment, that is exactly backwards.
Reach is not permission
Connecting an agent to an MCP server is usually a configuration decision: someone adds the server to a config file, and now the agent can see its tools. Nobody signed off on each individual capability. Nobody recorded which tools were in scope on which date. The agent's permitted actions are whatever the server happens to expose at the moment it is asked — and servers grow.
Consider a server fronting a core banking system. Today it exposes
read_balance and list_transactions. Next quarter a developer adds
post_journal_entry to support another team. Your read-only triage agent can now
move money, and not because anyone decided it should. The capability arrived by
deployment, not by authorization.
This is the difference between reach and permission. Reach is implicit, it drifts, and it leaves no record. Permission is explicit, it is granted to a named actor, and the grant is dated. When an examiner asks what your agent was allowed to do last March, "it could reach the server" is not an answer. The honest answer is: "whatever the server exposed in March, and we don't have that list."
A skill is a typed, versioned, tiered capability
MakerChecker treats each tool an agent may call as a first-class object it calls a skill. A skill is not a loose reference to a server; it is a specific capability the agent has been explicitly granted, and it carries three things the raw protocol does not.
A schema. The skill defines the shape of what goes in and what comes out — the parameters, their types, and the expected result. A call that does not match the schema is malformed and is refused before it reaches the tool. This is not a convenience. A typed boundary is the difference between "the agent invoked a function" and "the agent invoked this function with these arguments," which is the version of the event an auditor can actually read.
A version. Skill grants are versioned. When the underlying tool changes —
new parameters, a wider scope, a different endpoint — that is a new version of
the skill, granted deliberately, with a record of who approved it and when. The
quarter the bank added post_journal_entry, MakerChecker does not silently widen
your agent. The new capability is a new skill that nobody has granted yet, so the
door stays shut until someone with authority opens it on the record.
A risk tier. Not every tool deserves the same treatment. Reading a balance is not releasing a batch. A skill carries a risk tier, and the tier drives the controls around it: low-risk skills may run freely, high-risk skills route through an approval gate that parks the run and demands a named human signature before the call goes through. The protocol has no concept of "this call is the one that matters." Your control plane must.
Deny by default, at the level of the call
The governing rule is simple to state and load-bearing in practice: an agent can call a skill only if its role holds an explicit, current grant for that skill. Everything else is denied. Reaching the server grants nothing. Discovering a tool grants nothing. The list of doors an agent can open is the list someone wrote down — no more.
| Plain MCP connection | MCP skill under governance | |
|---|---|---|
| What the agent can call | Whatever the server exposes | Only explicitly granted skills |
| New tool on the server | Silently available | A new skill, denied until granted |
| Call arguments | Whatever the agent sends | Validated against a typed schema |
| High-stakes calls | Indistinguishable from any other | Tiered, routed to an approval gate |
| Record of authority | None | Versioned grant, dated, attributed |
This is the same posture covered in deny-by-default permissions for AI agents, applied at the exact point where an agent reaches into the real world: the tool call. Deny-by-default is only meaningful if the thing being denied is the unit of real action, and under MCP the unit of real action is the call.
Every call lands in the record
Because skills are explicit and typed, the audit trail can be specific. Each attempted call — granted or refused, succeeded or gated — lands in an append-only, hash-chained, cryptographically signed ledger. The record names the agent, the role it held, the skill and its version, the arguments, the outcome, and any human who signed a gate along the way.
A refused call is recorded as carefully as a permitted one. When your read-only
agent reaches for post_journal_entry and is denied, that denial is evidence —
proof the boundary held, available offline to anyone who wants to verify it
against the published spec without touching your systems. Silent failure teaches
an auditor nothing. A recorded refusal teaches them the control works.
This matters under the rules a regulated team already answers to. Tamper-evident audit trails are 21 CFR §11.10(e). Segregation of duties is §211.22 in pharma and the Wolfsberg four-eye standard in finance. None of these mention MCP, because none of them care about the protocol. They care about whether you can prove which actor was authorized to do which thing, and prove the record was not altered. A typed, versioned, tiered skill is how you answer that question at the level of the individual tool call.
Native, not bolted on
There is a reason this has to be native rather than a wrapper script. If governance lives in a separate layer that an agent can route around — a second MCP connection, a direct API call, a tool the agent found on its own — the control is theatre. MakerChecker is MCP-native: the agent's path to a tool is the governed path. Skills are how the agent reaches MCP servers, so there is no ungoverned side door, because the front door is the only door.
The same principle lets you put governance around agents you have already built, without rewriting them, and it is how a LangChain agent or an existing agent of any framework gets its tool calls mediated through proxy sessions rather than re-architected. The agent keeps its model, its prompts, and its logic. What changes is that the doors it can open are now explicit, granted, versioned, and recorded — instead of implicit in a server it happens to reach.
See how it works, or book a demo to watch an agent get blocked from calling a tool it was never granted — live.