MCPMay 2026 · 8 min read

Why I run MCP servers in production

Three months running a Model Context Protocol server fronting real production data. What broke, what didn't, and why the integration surface is now my favourite seam.

Darren MorganFull-stack engineer & founder
#01
/mcp-in-prod

I've been running a Model Context Protocol server fronting live production data for a little over three months. It started as an experiment — an MCP shim over Rentalstack's internal API so I could query bookings from Claude — and somewhere along the way it became the most important seam in the whole product.

This is a field report, not a tutorial. The MCP spec is well-documented elsewhere. What I want to talk about is what changed when I stopped treating MCP as a developer convenience and started treating it as a production integration surface.

The MCP server is now the most important seam in the product. Every new feature lives there first.

The setup

The Rentalstack stack is the usual: Next.js dashboard, Postgres, FastAPI for the bits that need to be fast. The MCP server is a separate Python process that re-uses the same domain layer as the API. It exposes a curated set of tools — not all 60+ endpoints, just the 22 a human (or a model) actually needs to do useful work.

# tools/bookings.py
@tool(description="Find bookings for a property in a date range")
async def find_bookings(
    property_id: str,
    start: date,
    end: date,
    *,
    ctx: Context,
) -> list[BookingDTO]:
    await ctx.require_scope("bookings:read")
    return await booking_service.find(property_id, start, end)

That ctx.require_scope call is doing a lot of work. Every tool call carries the operator's API key, which scopes what the model can see — exactly the same auth surface as the dashboard. No new permissions model. No bolted-on "AI mode". The model is just another client.

What I expected vs what happened

I expected the model to be the bottleneck. It wasn't. The model is fine — Claude in particular is excellent at chaining 4-5 tool calls to answer one operator question. What I didn't expect was how much the tool surface itself had to change.

  • Verbose responses are expensive. Every field you return costs tokens. I rewrote the DTOs to be terse and added an opt-in include= param. 40% context drop.
  • Error messages are the docs. Models read errors and self-correct. Cryptic 4xx messages waste turns. Now every error names the next tool to call.
  • Idempotency keys matter more. Models retry. Without idempotency, you double-book.

The seam

Here's the bit that surprised me. Once the MCP server existed, I stopped writing new dashboard features against the database. I wrote them against the MCP tools. The dashboard became another MCP client, just one that happens to be a React app instead of a model.

The benefit isn't architectural purity. It's that every feature ships with an AI surface for free. When a customer asks "can I export this report to my agent?" — the answer is already yes.

Every feature ships with an AI surface for free. That's the real unlock.

What I'd do differently

Three things, in order of how much they would have saved me:

  • Start with the tools, not the endpoints. The tool list is the product. The endpoints are an implementation detail.
  • Use streaming responses from day one. The token-by-token feel of an agent answering is half the magic.
  • Log every tool call with the model's reasoning. It's the best observability data I've ever had on a SaaS product.

Try it

If you want to see the shape of it, the AdRocketX MCP server is open source at github.com/darrentmorgan/adrocketx-mcp. It's 22 tools over the Meta Marketing API, same pattern. Wire it into Claude Desktop or Cursor and feel the difference.

MCP isn't a feature you bolt on. It's the integration surface you should have been building all along.

Keep reading

More on MCP.

Newsletter · beehiiv1,240 readers

One essay, every other
Sunday.

Long-form notes on shipping AI products as a solo operator. No roundups, no affiliate links, no growth-hacks. Unsubscribe in one click.

✓ free✓ ~2 / month✓ no spam