The first question every team asks about MCP is the wrong one: "should we build an MCP server for this?" The right one is "who else needs this tool, and do they live in our codebase?" MCP doesn't make an agent more capable. It makes a capability portable. If nothing is going to consume that portability, you've added a process, a transport, and a schema layer to call a function you already had.
We've shipped MCP servers for four clients this year — an invoicing back office, a logistics dispatcher, an internal design-system query tool, and one that we deleted three weeks in and replaced with twelve lines of TypeScript. That last one taught us more than the other three.
MCP solves distribution, not capability
Before MCP, every agent-to-system integration was bespoke: your app wired tools one way, Claude Code wired them another, a teammate's IDE didn't have them at all. Each new client meant re-implementing auth, re-describing schemas, re-testing edge cases. MCP collapses that N×M problem into N+M — one server, many clients, one place where the contract lives.
One server, many consumers — and the cost of that
What an MCP server actually moves out of your codebase
- The win is operational, not cognitive— the model doesn’t reason better because a tool arrived over MCP. It reasons exactly as well as it would with the same schema passed inline.
- Credentials stop travelling — the server holds the API key and the scope. Clients get a tool name, not a token, which is the single strongest argument for MCP in a regulated environment.
- Versioning becomes possible — you can deprecate a tool, change its shape, or add a guardrail without shipping four client releases in lockstep.
- Discovery is the underrated part — a new engineer points their editor at the server and immediately has the same twelve tools the production agent has, with the same descriptions.
Where it breaks: you pay for every tool on every turn
Tool definitions are prompt. They're serialized into the request on every single turn, whether the model uses them or not. Our logistics client connected three MCP servers, exposed 40 tools between them, and burned 31% of their prompt budget on schemas before the user had typed anything. Latency went up, cost went up, and — worse — tool selection accuracy went down, because eleven of those tools had overlapping descriptions.
The fix isn't a bigger context window. It's fewer, coarser tools. We stopped mirroring our REST endpoints one-to-one and started designing tools around the task the agent is actually trying to complete.
Returning "No match. Ask the user for the invoice number." instead of a 404 cut our retry loops roughly in half. An MCP tool's error strings are read by a model, not a human — write them as instructions for what to do next, not as status reports.
The rule: MCP for other people's clients, functions for your own loop
Here's the decision we make on every tool now, and it takes about thirty seconds. If the only caller is the agent loop you control, in the same repo, in the same deploy — it's a plain function. You get type safety, a stack trace, a debugger, and zero serialization. The moment a second, independently-deployed client needs it, or the credential can't be in that client's process, it earns an MCP server.
- 1Count the clients. One caller in one codebase means a function. Two or more independently-shipped consumers means a server — that's the whole test, and it's right most of the time.
- 2Check where the secret lives. If a tool needs a credential you wouldn't put in the calling process, MCP is the cheap boundary. This overrides the client count.
- 3Look at the return payload. Tools that return large or unbounded results (a full table, a whole file tree) belong behind a server that can paginate and truncate, because a plain function will happily blow your context window.
- 4Then trim ruthlessly. Cap what any one agent sees at roughly a dozen tools; if you're past that, you're modelling your API surface instead of the agent's job.
31%
of prompt budget spent on tool schemas before we trimmed the server list
40 → 9
tools exposed to the logistics agent after redesigning around tasks
1 of 4
MCP servers we built this year that should have stayed a plain function
“We stopped asking whether a tool could be an MCP tool and started asking who the second client is. If we couldn't name one, we deleted the server.”
Key Takeaways
- MCP is a distribution and credential boundary — it makes a capability portable, it does not make the model better at using it.
- Every connected tool costs prompt tokens on every turn; three servers and 40 tools measurably degraded both cost and tool-selection accuracy.
- Design tools around the task the agent is completing, not around your REST endpoints — one coarse tool beats six thin CRUD wrappers.
- Default to a plain function when you own the only caller; promote it to an MCP server when a second independent client appears or the credential can't live in-process.
Where to start
Take the agent you already have in production and log the prompt-token split between tool schemas and actual conversation for a week. If schemas are over a fifth of it, you have a trimming problem, not an MCP problem — and no amount of protocol will fix that. Once the tool list is honest, pick the single integration that two teams are duplicating and make that your first server. One real consumer on day one beats a platform nobody connects to.






