Platform Engineering14 October 20268 min read

MCP Without the Hype — Part 4 of 6

Design an MCP server as a product, not a wrapper

The fastest way to build an MCP server is to wrap an existing API, endpoint by endpoint. It is also the fastest way to create an unowned, over-powered integration nobody can support. Part 4 covers naming, schemas, errors, idempotency, limits, versioning and the owner every server needs after the demo.

#MCP#Platform Engineering#AI Engineering#Operating Model#AI Agents

There is a tool for almost every framework that will turn an OpenAPI document into an MCP server in minutes. Point it at the policy administration API, and every endpoint becomes a tool. It is a genuinely useful way to explore. It is a poor way to build something people will rely on.

A wrapped API inherits the API's shape, which was designed for developers who read documentation, not for a model choosing from a list. It exposes everything, including operations nobody should ask an assistant to perform. And it arrives with no owner, because the person who ran the generator was doing a spike, not taking on a service.

An MCP server that real people depend on is a product. It has users, the people working through AI applications, and consumers, the applications themselves. It needs the things any product needs: a clear purpose, a designed interface, support, an owner, a budget and a way to retire it. This part is about building it that way.

Kwelanga Insurance is fictional, and its systems and figures are illustrative. Kwelanga's first claims server was a wrapper, and so was its first policy server. By the time the platform team had narrowed the release in Part 1 and mapped its boundaries in Part 3, both needed rebuilding. This part follows that rebuild.

Do not wrap every API

Kwelanga's policy administration system has about 140 API endpoints. The generator produced 140 tools. The model, given 140 tools with developer-oriented names, did what any newcomer would do with a 140-item menu in a language they half understood: it guessed.

The team ran every endpoint through four questions:

  1. Will an AI client really use it soon? Not "could it", but "is there a named task in the next quarter that needs it?"
  2. Is there an owner who will run it? If nobody will answer for it when it misbehaves, it does not ship.
  3. Can it be named as one task? "Look up a policy" is a task. "Set the endorsementStatus field" is a step inside a task.
  4. Does it change data or money? If yes, it needs scopes, confirmation and audit designed before it exists.
Do not wrap every APIWill an AI client really use it soon?Leave it as an APInoyesIs there an owner who will run it?Not yet: no owner,no servernoyesCan it be named as one task?Compose a task-leveltool firstnoyesDoes it change data or money?Write tool with scopes,confirmation and audityesnoRead-only tool or resource
Kwelanga's policy administration system has about 140 endpoints. Run through these four questions, they became four tools. Most endpoints failed the first or third question: nobody would ask for them, or they only made sense as one step inside a larger task.

Most endpoints failed the first or the third question. The policy server shipped with four tools: lookup_policy, get_cover_summary, get_excesses and get_policy_documents, the last returning links to the policy wording as resources rather than pasting it into a result. Everything else stayed an API, available to ordinary software and invisible to the model.

Design: what the model and the client see

Naming. Name tools for the task a person would ask for, with a verb they would recognise. The specification asks that tool names be unique within a server, limited to letters, digits, underscores, hyphens and dots, and treated as case-sensitive. It also warns that clients aggregating several servers may meet name collisions, such as two servers each exposing search, so a name that says what is being searched for is kinder to everyone.

Schemas. Make inputs tight. A claim number has a format; validate it. A date has a range; enforce it. The 2026-07-28 specification, checked on 14 October 2026, uses JSON Schema 2020-12 for inputs and lets a tool declare an outputSchema, in which case the server must return structured results that conform and clients should validate them. Structured output is a contract, not a formatting preference: it is what lets the host check a result before the model reads it.

Errors. The specification separates protocol errors, such as calling an unknown tool, from tool execution errors, which are returned as a result with isError set to true so the model can see them and correct itself. Write execution errors for that reader. "Claim KW-2026-118734 is not assigned to you; ask your team leader to reassign it" helps a model and a person recover. A stack trace helps an attacker.

Idempotency. Any tool that writes must be safe to retry. Networks drop, and under the current specification a broken response stream loses the in-flight request, which the client must then reissue as a new request. Kwelanga's add_file_note requires a client-generated key per note; a second call with the same key returns the first note instead of creating a duplicate.

Pagination. Never return "everything". list_my_open_claims returns twenty claims and a cursor. A handler with 300 open claims is a workload problem, not a reason to put 300 claims into a model's context.

Operation: what keeps it trustworthy after the demo

Rate limits. The specification says servers must rate limit tool invocations. Set limits per caller, not only per server, so one runaway agent cannot exhaust the quota for every handler.

Versioning. A tool's name, description and schema are its interface. Changing them changes what every connected model does. Kwelanga version-controls tool definitions with the server code, reviews description changes like code changes and adds a new tool, rather than silently changing an old one, when behaviour changes meaningfully.

Support. Someone has to watch a queue. When a handler reports that Kwelanga Assist "keeps saying the claim is not mine", there has to be a person who can tell whether that is an assignment problem, a token problem or a bug.

Ownership. Every Kwelanga server now has a named product owner in the business and a named engineering owner in the platform team. The claims server's product owner is the claims operations manager, because she decides which claim tasks an assistant should support. The engineering owner decides how.

Deprecation. Announce, give notice, then retire. The protocol itself models this well: its feature lifecycle policy keeps deprecated features in the specification for at least twelve months before removal. Your own servers need a policy too, even if the window is shorter.

What turns an endpoint into a productDESIGNOPERATIONNAMINGVerbs a personwould recogniseSCHEMASTight inputs,typed outputsERRORSErrors that sayhow to recoverIDEMPOTENCYSafe to retrywithout repeatsPAGINATIONBounded pages,never everythingRATE LIMITSPer caller,not per serverVERSIONINGChange withoutbreaking clientsSUPPORTA queue someoneactually watchesOWNERSHIPA named ownerand a budgetDEPRECATIONNotice first,then retirement
The top row is design: what the model and the client see. The bottom row is operation: what keeps the server trustworthy after the demo team has moved on. Kwelanga's first wrapper servers had none of the bottom row and only some of the top, and the rebuild started with ownership.

Redesigning one write tool

add_file_note is the tool that taught Kwelanga the most, because a file note is part of the legal record of a claim. The wrapper version took a claim ID and a text field, used the shared service account and wrote immediately. The product version works differently:

  • It acts with the handler's delegated identity, and the claims platform checks assignment.
  • It requires an idempotency key.
  • It refuses notes on claims flagged as in litigation, returning an execution error that says why.
  • It asks the person to confirm. Under the 2026-07-28 specification, a server can respond to a tool call with an "input required" result asking the client to collect information from the user, a pattern the specification calls elicitation. Kwelanga uses it to show the exact note text and the claim it will be attached to, and the host only retries the call after the handler confirms. Kwelanga Assist also shows its own confirmation, because a server-side request is only useful if the host presents it honestly.
  • It writes an audit record of who asked, through which application, with what text and with which result.

None of that is exotic. It is what a careful team would build for any internal write API. The only difference is that a model, rather than a form, proposes the call.

State without sessions

The current specification removed protocol-level sessions. A server that needs state across calls returns an explicit handle and receives it back as an argument. Kwelanga's first draft of a "prepare note, then submit" flow used a sequential draft number as the handle. The security review in Part 5 caught it: anyone who could guess the next number could submit someone else's draft. The specification's guidance is clear that a handle is a name, not a capability, so the server must check on every call that the caller owns it. Kwelanga switched to random handles bound to the handler's identity and an expiry of 30 minutes.

Who owns the MCP server after the demo?

The honest answer in most organisations is "the developer who built the demo, until they leave". That is how unowned integrations accumulate: servers nobody patches, descriptions nobody reviews, service accounts nobody rotates.

Kwelanga made one rule that did more than any technical control. No MCP server is connected to a production host without an entry in the platform team's service catalogue naming its two owners, its tools and their risk tiers, its data classification and its retirement date if it is temporary. Two community servers a developer had installed for convenience failed that rule and were removed.

Key points

A wrapped API is a spike, not a service. It inherits a developer-oriented shape and exposes far more than any assistant needs.

Four questions filter the endpoints. Real use soon, a named owner, a task-shaped name, and a known consequence for anything that writes.

Design for the model and the client. Task names, tight schemas, output schemas, recoverable errors, idempotent writes and bounded pages.

Operate it like a product. Per-caller limits, versioned definitions, a support queue, two named owners and a deprecation policy.

No owner, no server. A catalogue entry with owners and risk tiers should be the gate to production.

Next: Part 5, The MCP security review. All parts are on the series page. For the cloud-operations version of the same discipline, see The cloud API is the contract.

How CloudNala can help

We help platform teams turn MCP prototypes into supportable services: filtering which capabilities deserve a server, reshaping endpoint wrappers into task-level tools, designing write tools with idempotency, confirmation and audit, and setting up the ownership and catalogue rules that keep servers from going stale after the demo team moves on.


Work with CloudNala

CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.

Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.

Book an MCP Security Review or write to us at consult@cloudnala.co.za