Trust the harbor pilot
Lessons from designing MCP tools for AI agents
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?
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.
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.
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.
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.
{ "captureCount": 12 }vs.
{ "captureCount": 12, "capturesRemaining": 88, "burst": { "perMinute": 30, "usedThisMinute": 22 }, "notices": ["8 captures until session cap"], "actions": [ { "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_counttool, 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[]withlabel/cost/effect/urlgot 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_caporcap_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_claimednotice 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 docs.
Ask the agent — Asking an agent is the best reviewer of your build. The pre-build design review redesigned schemas, added pacing semantics and cut features. Post-hoc feedback finds bugs; pre-build review prevents bad shapes.
Receipts
Taking time to optimize your MCP implementation is time well spent.
Rejected sends during an 80-event bulk run — Before optimizing: ~50 (429s), After: 0
Full anonymous funnel, wall clock — Before optimizing: ~20 min, After: ~7 min
Post-signup re-orientation — Before optimizing: ~4 min, After: 21 seconds
Local echo receiver setup — Before optimizing: 1m 46s of shelling a daemon, After: 3 seconds, one tool call
Hand-rolled shell commands — Before optimizing: many, After: zero
And the reviewing AI’s verdict, verbatim: "I did not reach for ngrok or Stripe CLI first. I captured, watched, replayed, and explained. That's exactly the product motion you want."
Try on your agent
Before you point an agent at it, the fine print. The no-signup session is plaintext and expires (about 90 minutes, 100 captures), and the tools tell the agent not to send production or PII data there; claiming the session moves everything into an encrypted project. Test-event signatures are realistic shapes, not real signatures, and the tool says so. And it's stdio only for now, so Claude Code, Codex CLI, and Cursor work; ChatGPT and claude.ai web don't yet. The token your agent gets is read-only and redacts PII by default, and signup links go to your browser, never the agent.
If you would be kind enough to comment on your experience I would love to hear it.
claude mcp add flurryport -- npx -y flurryport mcpcodex mcp add flurryport -- npx -y flurryport mcp[mcp_servers.flurryport]
command = "npx"
args = ["-y", "flurryport", "mcp"]Ask it to debug a webhook handler and watch which tools it picks. Docs at flurryport.io/docs/cli.



