leanlift.ai
← All posts

Designing MCP tools that earn their keep

Most MCP servers expose a database. The useful ones expose the operations a business actually performs — and that distinction decides whether an assistant is trustworthy.

LeanLift2 min read

The quickest way to build a Model Context Protocol server is to wrap your tables: list_orders, update_order, delete_order. It demos well and it is almost always the wrong shape.

Model operations, not rows

A support agent does not "update an order". They resolve a refund, which means checking eligibility, writing a ledger entry, notifying the customer, and leaving an audit trail. If the tool is update_order, the model has to invent that sequence every time, and it will invent it differently every time.

// Wrong shape: the model has to know your invariants.
updateOrder({ id, status: 'refunded', refundAmount: 4200 });

// Right shape: the invariants live in the tool.
refundOrder({ id, amount: 4200, reason: 'damaged_on_arrival' });

The second version can enforce the refund window, reject an amount above what was captured, and be idempotent on retry. None of that is achievable when the tool is a thin passthrough.

Scope every tool separately

A single "read-write access to production" token is not a permission model. Each tool gets its own scope, and the transport carries a short-lived credential:

  • catalog.search — read only, no auth beyond tenancy
  • content.publish — write, requires an editor role
  • order.refund — write, capped by amount, always audited

Measure before and after

Once a workflow is live, a model upgrade is a production change. Keep an evaluation set of real requests with known-good outcomes so you can answer the only question that matters: did this get better or worse?