Lessons from designing MCP tools for AI agents

spillcoffee1 pts0 comments

Trust the harbor pilot - by Gene Beal

SubscribeSign in

Trust the harbor pilot<br>Lessons from designing MCP tools for AI agents

Gene Beal<br>Jul 09, 2026

Share

Model Context Protocol (MCP) seems like a simple enough task to achieve. You already have an API for your application that your UI uses, recycle relevant pieces through code re-use and wrap them nicely for AI to digest. An AI digesting MCP implementation should just know to reach for your tool over rolling their own; their user installed it didn’t they?<br>That was my thought anyway.

Quick context for new readers: FlurryPORT captures your incoming webhooks at a stable URL and replays them into your local app, signatures intact. I set out in a design session with AI to come up with the key areas that should be implemented. Discussed security concerns and wrapped them into the plan. I even spent an entire afternoon scrutinizing an upgrade path from my free offering at FlurryPORT.dev/try. A few coding sessions later and my product had an effective MCP stdio implementation — or so I thought.<br>I fired up a rival coding AI to what I used as a coding aide and started prompting. I started with non-leading questions to mimic a user who hadn’t thought through their prompts, but loosely knew about how to go about their task. I quickly found that AI was grasping at every tool it could imagine to send/receive webhooks except those provided by my implementation.<br>I decided to stop my test and just ask directly: how was this MCP implementation, what would make it better? I was surprised how easy it was to gather requirements and I learned a few things. I then handed the next version of design back to the test AI agent to review before building it.<br>Design MCP tools for agents

Make polling rewarding — Having bland data that isn’t expressive is not appealing to AI. This I found counter intuitive, in that isn’t AI just a computer and shouldn’t it just derive all sorts of usefulness give raw numbers. This I found counterintuitive: isn't AI just a computer, and shouldn't it derive all sorts of usefulness given raw numbers? But the model isn't calculating, it's reaching for whatever most reliably moves the task forward, and a bare number gives it nothing to act on. The difference is easy to see in the payload.<br>{ "captureCount": 12 }

vs.<br>"captureCount": 12,<br>"capturesRemaining": 88,<br>"burst": { "perMinute": 30, "usedThisMinute": 22 },<br>"notices": ["8 captures until session cap"],<br>"actions": [<br>{ "label": "Claim this session to keep captures", "cost": "free", "effect": "removes cap", "url": "https://flurryport.io/claim/..." }

Affordances beat prose — A paragraph informing AI that it should pace requests to the server was ignored. A simple capture_count tool, whose description says what it's for, got called between every batch. If you find yourself writing guidance prose, ask what tool would make the guidance unnecessary.

Return structured facts — Receipts, diagnosis codes and an action[] with label/cost/effect/url got relayed to the user verbatim on every run. A canned explanation with well crafted prose was our tool trying to do the model’s job. Let the model narrate for its user and give it understandable facts.

Stable codes over polished copy — An agent will key on at_cap or cap_would_exceed, not sentence wording. Having machine readable state made behavior more deterministic where prose set AI off improvising on how to proceed. Error strings are UI; codes are API.

Refuse before acting — A partial success creates what the reviewing agent called “explanation debt”. Sending 7 of 10 events forces an agent to narrate to its user. A clean refusal that says “send at most N” produced clean behavior instantly. Check the whole request against available budget before processing any of it.

Transitions need a map — If tooling changed or data was migrated based on a conversion event (like FlurryPORT’s anonymous-to-account flip) provide that change mapping to the AI agent. Without a breadcrumb the AI agent spent 4 minutes exploring tools to rediscover what just changed. When mapping was provided it performed the same task in 21 seconds. As a follow up to this one, tools that keep their names across a transition should keep compatible schemas too; AI clients cache schemas imperfectly.

One shot notifications get lost — A session_claimed notice was lost by a mid-batch poll and the agent never informed the user their upgrade was successful. Anything that an agent must not miss must be a durable field on every response, not on a single event.

Don't rely on agents to run daemons — An agent spent 1m 46s backgrounding a shell process to stand up a receiver for its user. Replacing it with tooling available within the implementation brought that time down to 3s (eg. start_echo_server).

Tool descriptions are your routing layer — “CALL THIS FIRST” in a description is a reason four cold runs never reached for ngrok or the Stripe CLI. Discoverability is written into descriptions not the...

agent user tool tools implementation agents

Related Articles