Tempio

MCP is a contract, not a feature

Tempio5 min read

A protocol appearing on a feature list tells you almost nothing. It says two programs can exchange messages in a shared format, which is the beginning of an integration rather than the substance of one. The interesting questions are all about what the server does with a message once it has parsed it.

What the badge does not tell you

Two servers can both speak the same protocol and differ on every question that matters.

Whether a credential can reach a tenant other than its own. Whether the tool list a client receives reflects what that client may actually call, or is the full catalogue with refusals waiting behind half of it. Whether the descriptions a model reads were written by hand months ago or generated from the code that will run. Whether a write goes straight out or becomes something reviewable. Whether an identifier supplied by the caller is trusted.

None of that is visible from the fact of support. All of it decides whether pointing an agent at the thing is a good idea.

The contract, in four clauses

The tenant is derived, never named. The workspace comes from the verified credential and not from any argument, and no capability accepts one. This is worth more than it sounds, because it removes an entire class of problem rather than defending against it: there is no parameter to tamper with, no identifier to guess, and an identifier from somewhere else produces no row and therefore no answer.

The tool list is the permission list. Capabilities are registered per request against the scopes the credential carries, so a read-only credential never receives the drafting ones. An agent cannot be argued into calling something absent from its list, which is a guarantee that costs nobody any vigilance. Where a surface is deliberately compact — two tools that dispatch onto everything — the same rule holds one level down, and a refusal names the scope needed and the scopes held so the caller is told what to ask for rather than concluding the capability does not exist.

The catalogue is generated. The description a client reads is produced at request time from the same tables the calls run on: the route table, the payload schemas, the warning registry and each live connection's own capabilities. Hand-written documentation drifts from the implementation, quietly, and a model reading drifted documentation will call things that do not exist and describe behaviour that was removed. Generating it means discovery, description and execution agree by construction.

There is one tool layer. The programmatic surface and the product's own agent call the same organisation-scoped functions rather than two implementations of one idea. A capability behaves identically whichever client invoked it, and a correction lands in both at once. Two code paths for the same operation is how a system develops a personality: things that work in one interface and not the other, for reasons nobody can explain.

The envelope is part of the contract too

A result that varies in shape by capability is a result every caller has to special-case. Assembling it in one place for every call means the shape cannot drift.

What that buys is specific. A statement of what a scope actually covered — its currency, which is empty when the scope spans several, the time zone the dates are in, the range, the entity level, and whether the rows returned are all of them. A warnings list that is always present and empty when there is nothing wrong, with each entry carrying a class to branch on, a message saying what the condition means for the answer it travels with, and a link to the record it is about. An unknown code degrades to a generic class rather than failing the call, so a server can add a warning without breaking a client.

And a warning never changes a value. A currency warning does not round a number and a staleness warning does not hide one — which is the difference between a system that annotates uncertainty and one that resolves it on your behalf.

Why a write has to be different in kind

The clause that decides whether any of this is safe is what happens when a caller asks for a change.

If a write goes straight through, every guarantee above is decoration: the agent has an ad account and a network connection, and the protocol was the delivery mechanism. If a write becomes a reviewable record first, the guarantees compose into something you can reason about.

So the clause reads: the server may read a connected account, and may not change one on its own authority. A change arrives as a record rather than as an effect, carrying its prior value and the checks it cleared, and it waits for you or for a rule you wrote. The last clause is the one a wire format cannot express — no platform write reaches a customer account until that platform has granted write access, and the apply itself is in private beta.

That is the clause a comparison table cannot hold, and it is the one that matters. Everything else is how the message arrived.

What to ask a vendor

Four questions, and they take a minute each.

Can a credential reach a workspace it was not issued for, and is the answer enforced by a check or by the absence of an argument. Does the tool list depend on what the credential may do. Is the catalogue generated from the running code. And what happens to a write — does it go out, or does it become something a person or a rule has to clear.

The answers will not be on the feature page, because none of them fit in a column. That is roughly the point: supporting a protocol is a fact about a wire format, and the contract is everything a wire format does not say.

An agent with your ad account is the same argument from the customer's side, and Connect any MCP client to your accounts is the procedure.

Read next

Questions

Put frontier AI to work on every ad account you run.

Tempio connects your ad accounts into one workspace and hands your own AI the numbers and the tools. Every change it writes is a draft until you approve it, or until a rule you wrote does.

Request early access
  • Read and draft by default. Approve is a separate permission you grant.