The Protocol Solved the Easy Half

Model Context Protocol did something genuinely useful: it standardized how an AI client discovers and invokes tools. Any MCP-speaking client — a desktop assistant, an IDE, an autonomous agent — can connect to any MCP server and start acting. The plumbing question is settled.

What the protocol deliberately does not settle is the enterprise half of the problem. Where do tool definitions come from, and how do they stay true to the systems they describe? And when an AI client asks to act, who decides what it may do? Most early enterprise MCP deployments answered both questions the same way: with hand-written wrapper code. A developer reads the API docs, writes a tool schema, embeds some permission checks, and ships a server. It works in the demo. It is also two time bombs in one artifact.

Wrapper Rot: Tools That Lie About the System

The first time bomb is drift. A hand-written wrapper is a copy of the API's shape, made by a human, frozen at authoring time. The API keeps moving — a field is renamed, a validation tightens, an enum grows a value, a domain action changes its preconditions. Nothing forces the wrapper to move with it. Documentation rot is an old story, but tool rot is worse, for one reason: the consumer of a rotten tool definition is a language model that cannot tell it is being lied to.

A human developer reading stale docs eventually notices the 400 errors and investigates. A model given a stale tool schema will keep constructing plausible calls against a shape that no longer exists — or worse, calls that still succeed but no longer mean what the schema says they mean. The failure is silent, confident, and repeated. In an enterprise, "the AI acted on a false description of the system" is not a bug report; it is an incident review.

WRAPPER ROT vs. GENERATED CONTRACT HAND-WRITTEN WRAPPER API today: v1.6 fields renamed, actions changed drift tool schema: written at v1.1 updated when someone remembers MODEL ACTS ON v1.1 TRUTH silent, confident, wrong rot compounds with every release GENERATED FROM CONTRACT OpenAPI contract: v1.6 the same spec the UI runs on regenerate openapi-to-mcp: v1.6 rebuilt on every publish MODEL ACTS ON v1.6 TRUTH tools cannot describe a stale API drift is structurally impossible

Fig 1 — A wrapper is a copy of the API that ages independently. A generated server is a projection of the API that cannot age at all.

Generation: Tools as a Projection of the Contract

Own360's answer is to never write tool definitions by hand. Every one of the 23 apps already publishes a versioned OpenAPI contract at /api/v1 — the same contract the UI, the CLIs, and raw HTTP clients use, as described in Headless by Contract. The openapi-to-mcp generator projects that contract into MCP tool servers mechanically: operations become tools, request schemas become input schemas, RFC 9457 problem details become structured tool errors, and domain actions — the same advance_deal a sales rep triggers from a button — become invocable tools with their real preconditions intact.

The property this buys is not "less typing." It is truthfulness by construction. The tool layer cannot disagree with the API because the tool layer is not a second description of the API — it is the same description, re-rendered. When the contract changes, regeneration is part of publishing, the way compiling is part of shipping. There is no window in which an AI client can hold a schema the platform no longer honors.

Generation also inherits the contract's operational guarantees. Cursor pagination means a tool that lists ten thousand records behaves correctly. Idempotency-Key support means an agent that retries a timed-out write cannot double-create an invoice. These behaviors were engineered once, in the API, and every tool gets them without a wrapper author remembering to implement them.

A hand-written tool is a second source of truth, and second sources of truth always diverge. A generated tool is the first source of truth wearing a different interface.

The Permission Question Does Not Belong in the Tool

The second time bomb in wrapper-style MCP is authorization. When permission checks live inside tool code, you have as many security models as you have tools, each maintained by whoever wrote the wrapper, none of them visible to the people who own access policy. The question "what can our AI clients actually do?" becomes unanswerable — the answer is smeared across a hundred if-statements in a dozen repositories.

The correct architecture is boring and classical: tools describe capabilities; the control plane decides permissions. In Own360, an MCP client authenticates through OAuth2 client-credentials and holds a scoped grant issued by OwnCentral — the same identity and RBAC system that governs every human and every agent. When a tool call arrives, the MCP server does not consult its own opinion. The request flows through the API gateway, OwnCentral evaluates the client's grant against the operation — in under 5ms at p99, so per-call authorization costs nothing perceptible — and only then does the app execute.

AN MCP CALL'S PATH THROUGH THE CONTROL PLANE AI CLIENT tool call MCP SERVER generated, stateless OWNCENTRAL identity + scoped grant check RBAC eval <5ms p99 APP /api/v1 executes operation out of scope → RFC 9457 denial IMMUTABLE AUDIT LOG: client · tool · grant · decision · result

Fig 2 — The generated MCP server holds no policy. Every call is authorized by OwnCentral and lands in the same audit log as human actions.

Scoped Grants: Least Privilege for Non-Human Clients

Because AI clients are first-class identities, they get what human roles have always had: least privilege, expressed as scopes. A support-facing client might hold read access to CRM entities and write access to Desk tickets — and nothing else. A finance automation might invoke ERP and Books operations but never see HR data. The scope is attached to the client's grant in OwnCentral, not to the tool definitions, so tightening a client's reach is a policy edit, not a redeploy of tool servers.

This is also how the same MCP surface safely serves very different trust levels. The 6 OwnAgents — DealAgent, HireAgent, SpendAgent, ComplianceAgent, SupportAgent, OpsAgent — each hold grants shaped to their job. An experimental client someone connects from an IDE can be granted read-only scopes on a sandbox. One tool catalog, many clients, each seeing exactly the slice policy allows — a direct application of the zero-trust posture agents require.

CAPABILITY SCOPING BY CLIENT GRANT crm.deal read crm.deal write books.invoice write desk.ticket write DealAgent yes yes SpendAgent yes SupportAgent yes yes IDE client (sandbox) read-only same tool catalog for every client — the grant, not the tool, decides what is reachable

Fig 3 — Scopes live in OwnCentral grants. Changing a client's reach is a policy edit, never a tool-server redeploy.

The Audit Trail: What Did the AI Actually Do?

Every MCP-driven action lands in OwnCentral's immutable audit log with the full decision context: which client, which tool, which grant, what the authorization decision was, what the operation returned. Because MCP calls resolve to the same API operations as everything else, the audit record for "an agent advanced this deal" is structurally identical to "a rep advanced this deal" — one log, one shape, one query surface, which is what makes agent observability tractable rather than aspirational.

And because every write emits an entity.changed event on OwnBus, MCP-driven changes are visible to the rest of the platform the instant they happen. Nothing about an AI client's action is quieter than a human's. That symmetry — same contract, same authorization, same audit, same events — is the entire point.

Tools Are Promises

An MCP tool definition is a promise to a reasoning system: this action exists, takes these inputs, and means this. Enterprises should hold that promise to the same standard as any API contract, because that is what it is. Hand-written wrappers break the promise slowly and silently. Generated servers keep it mechanically. And a control plane that owns the permission question keeps the other promise — the one you make to your auditors — that you always know what your AI clients can do, and can prove what they did.

MCP gave every AI client a socket into the enterprise. The contract, the grant, and the audit log are what make plugging things into that socket a reasonable thing to do.

Connect any MCP client to 23 governed apps

Own360 generates MCP tool servers from the same OpenAPI contracts that power the UI — with scoped grants and per-call authorization from OwnCentral.

See it live →

Related posts

Security Zero Trust for AI Agents: Why Your Security Model Needs a Rewrite Observability Agent Observability: You Can't Govern What You Can't See Infrastructure The Enterprise Agent Stack: What You Actually Need to Ship