Skip to content
← Back to News

Specs10 min read

An open runtime: typed tools, scoped auth, and a human on the write path

MCP gives tools a common shape. It says openly that it cannot enforce safety at the protocol level — that part is yours. Here is what has to be built on top, and why we build it that way.

If you are integrating a tool into an agent runtime, the interesting question is not what the protocol lets you send. It is what the runtime on the other side promises to do before it runs what you sent.

1. What MCP standardises

The Model Context Protocol is «an open protocol that enables seamless integration between LLM applications and external data sources and tools». It runs over JSON-RPC 2.0 and names three roles: hosts (the application), clients (the connectors inside it) and servers (whatever provides capability).

A server offers three kinds of thing, and the distinction matters when you design an integration:

  • Resources — context and data, for the user or the model to read.
  • Prompts — templated messages and workflows, offered to the user.
  • Tools — functions the model can execute.

The value of that is the same as the value of any protocol: an integration written once works against anything that speaks it. That is worth adopting on its own.

2. What it explicitly does not do

This is the part worth reading twice, and the specification is admirably direct about it. On safety it says implementors must obtain explicit user consent before invoking any tool, that a tool is arbitrary code execution, and that a tool's own description «should be considered untrusted, unless obtained from a trusted server».

3. Typed contracts: what a tool has to declare

A tool that takes free-form input is a tool you cannot reason about. The contract has to say four things before the call is worth making:

  1. What it takes, with types and constraints — not just names. A field typed as «string» constrains nothing.
  2. Who it is for. Every call carries the customer it acts on behalf of, and the tool checks it rather than trusting it.
  3. What it returns, in a shape the caller can validate. A tool that returns prose has moved the parsing problem, not solved it.
  4. Whether it writes. A tool that only reads and a tool that creates an order are not the same risk and should not travel the same path.

That last distinction is the one most integrations skip, and it is the one that decides what has to happen next.

4. Scopes: default deny, and check where it matters

Two rules do most of the work here, and neither is exotic:

  • Deny by default. A call without credentials, or with a signature that does not verify, is refused — not degraded, not logged and allowed through.
  • Check the tenant at the service, not at the gateway. A gateway that authenticates and then forwards trusted calls turns any internal mistake into a cross-customer one. The service that owns the data is the one that has to confirm the caller is who the URL says.

There is a third, less obvious: a credential that is valid forever is a credential you cannot revoke in practice. A short validity window with a replay guard costs almost nothing and removes an entire class of problem.

5. A human on the write path

The specification says the host must obtain explicit consent before invoking a tool. In a conversational product that cannot mean a dialog box on every call — nobody would use it. It means deciding, in advance, which actions stop.

Kind of actionWhat should happen
Read: look up a price, check stockRun it. Log it. No interruption.
Write, reversible: create a draft, reserve stock with an expiryRun it, and make the reversal as easy as the action.
Write, irreversible or money-movingStop. A person confirms, and the stop is a deterministic step in the flow, not a prompt asking the model to be careful.
Hand-off to a person, dispute, refundStop, and make the stop the normal path rather than the exception.
The distinction is not how confident the model is. It is whether the action can be undone.

That word deterministic is carrying weight. An instruction in a prompt telling the model to ask before acting is a request, and a request is not a control. The interrupt has to live in the code that dispatches the call.

6. The life of a tool call

  1. Authenticate and scope. Who is calling, on behalf of whom, and is that credential still valid?
  2. Validate the input against the declared contract, before anything runs.
  3. Decide whether it stops. Read, reversible write, or irreversible — the classification is the tool's, not the model's.
  4. Execute against the system that actually owns the data.
  5. Validate the output the same way you validated the input.
  6. Record it. What was called, by whom, for which customer, with what result. If you cannot reconstruct that afterwards, you cannot answer the only question that matters when something goes wrong.

7. Implementing your first tool

The advice that saves the most time is about ordering. Build the read-only version first, with its contract declared and its input validated, and get it working end to end. Only then add anything that writes — and when you do, decide its reversibility class before you write the code, not after.

Mounting MCP alongside an existing HTTP interface rather than replacing it is worth doing for the same reason: consumers move one at a time, and nothing has to be switched off for the first integration to work.

The specification, and where to read it

Everything quoted above is from the MCP specification itself. It is short and worth reading in full, particularly the security section.

  • modelcontextprotocol.io — MCP is «an open protocol that enables seamless integration between LLM applications and external data sources and tools», over JSON-RPC 2.0, with three roles: hosts, clients and servers. A server offers resources, prompts and tools.
  • modelcontextprotocol.io — «Hosts must obtain explicit user consent before invoking any tool», and a tool's descriptions «should be considered untrusted, unless obtained from a trusted server»: a tool is arbitrary code execution.
  • modelcontextprotocol.io — And it says so of itself: «MCP itself cannot enforce these security principles at the protocol level». Consent and access control are for the implementor to build; the protocol only recommends them.

Specification checked on 2026-09-29. MCP is versioned by date, so check against the revision you are implementing.

Frequently asked questions

What does MCP actually standardise?

The shape of the conversation between an application and a capability: JSON-RPC 2.0 messages, three roles, and three kinds of thing a server can offer — resources, prompts and tools.

Does MCP make tool calling safe?

No, and it says so: it cannot enforce its security principles at the protocol level. It sets out what implementors must do — consent before invoking a tool, treating tool descriptions as untrusted — and leaves the enforcing to the runtime.

Do I need human approval on every tool call?

No, and a product that asks on every call will not be used. Classify by reversibility: reads run, reversible writes run with an easy undo, and irreversible or money-moving actions stop for a person.

Can I adopt MCP without replacing my existing API?

Yes, and it is the lower-risk path. Mounted alongside the existing routes, consumers migrate one at a time and nothing has to be switched off for the first one to work.

Keep reading