some more learnings from pm-ing an mcp
i've written about the predictability quadrant, about treating agents as a new user persona, and about the empathy canvas that comes out of that. if you've read the new user persona, you already have the thesis: tools aren't api wrappers, responses should teach the agent what to do next, build for the weakest model. this one skips the thesis and goes straight to what actually building tools this year taught me that i hadn't written down yet.
the short version: you will never control the agent calling your tool. not the model, not the harness, not how careful its prompt is. someone will connect claude to your mcp server. someone will build their own weird agent on top of it. your tool has to work for all of them, and the only thing you actually get to design is the tool itself and the instruction that comes with it. everything else is out of your hands. that reframes a lot of decisions that look like tool design questions but are really packaging questions.
there's a version of "make the agent do less work" that turns into "so we need more, narrower, hyper-specific tools." wrong lesson. more tools means more composing, and composing is exactly the kind of work you were trying to remove.
concrete example: create and update collapsed into a single tool. "set this condition to x," creating it if it's missing, updating it if it's there. splitting that into two tools mirrors REST conventions built for deterministic callers, not what the agent is actually trying to do.
better one: we almost built a separate "submit" tool after "create contract," reasoning that splitting form-fill from submission would reduce confusion. except the contract's always sitting in draft regardless of submission, so the split just gave the agent a clean spot to fail and then have to rewrite fields it already got right the first time. cut the submit tool entirely. one tool commits everything it validly can every time, and if part of it fails validation, it tells the agent which fields landed and which need a patch. the agent never has to restart from zero because one field was wrong.
and no, this doesn't mean building a narrower toolset per specialized agent either. keep the toolkit shared and harness agnostic. what changes per agent is what gets surfaced and how hard the description leans on steering it toward the right tool, not the existence of five almost-identical tools carved out for five almost-identical callers.
we built the same workflow builder capability on two different harnesses with the same three tools: an analyzer, a document generator, an executor. nobody told either harness that generation and execution were independent. claude figured it out anyway and spun up two sub-agents to run them in parallel. neo (our internal tool), given the identical tools, just ran everything one after another, because nothing told it that was an option.
that's not a hole in "treat the harness as a commodity," it's the actual edge of that rule. tools and instructions should get you the same outcome everywhere. whether a harness notices an optimization and takes it on its own initiative is a harness capability, not something you can write into a tool description. if you need that parallel execution on a harness you actually control, design it in on purpose. don't wait for it to get discovered.
it's easy to forget the normal rules of building a service still apply once there's an agent in front of it. ten records to update means a bulk tool, not ten parallel calls that trip a limit. and when a limit does trip, respond the way you'd want a 429 to read: you're calling this too often, back off, don't just fail silently. this is also another argument for consolidating tools in the first place, every extra tool call is an extra hit on whatever's underneath it, not only an extra turn of the model thinking.
one thing nobody plans for: building an mcp tool on top of an existing api is a pretty good way to find out how much validation logic only lives on your frontend. you end up either duplicating it into the tool wrapper or finally pushing it down into the backend where it belonged the whole time. i'd take the forcing function. it's free architecture review you didn't schedule.
none of this needed a smarter model to fix. it needed someone to sit down, look at where an agent was burning tool calls, and decide that was a packaging problem, not a prompting problem.