Last month I watched a team spend nine days building an MCP server to fetch weather data. Nine days. The agent could've hit the API with a single curl and a one-line tool definition. But MCP was the shiny thing, so MCP it was.
Let me say the quiet part loud: you should stop building MCP servers for everything. The Model Context Protocol is genuinely good. It's also wildly overapplied by people who heard "standard" and assumed "mandatory."
What MCP is actually for
MCP solves a real problem: you have a capability you want to expose to many agents, across many clients, with a consistent interface. Think a database your whole org queries. A design system. An internal search index that twelve different tools need to hit. Build the server once, and Claude Desktop, Cursor, and your custom harness all speak to it the same way. That's the win. Reuse across clients.
That's it. That's the whole pitch. If you're not getting reuse across multiple clients or multiple agents, you're paying the protocol tax for nothing.
The tax nobody mentions
Every MCP server is a process. It has a lifecycle. It has a transport — stdio or SSE — that can hang, drop, or silently stop responding. It loads tool definitions into your context window whether you call them or not. I've seen a single chatty MCP server eat 4,000 tokens of context before the model reads a word of the actual task.
And you have to maintain the thing. Version it. Handle auth inside it. Debug it when the agent says "the tool isn't responding" and you have no idea if it's the server, the transport, or the model hallucinating a tool name.
Compare that to a plain old function the agent calls directly, or a CLI command it runs through Bash. When my Claude Code agent needs to hit the GitHub API, it runs gh. No server. No protocol. No lifecycle. The tool is already on the machine and the model already knows how to drive it.
The honest decision rule
Here's the test I actually use before writing a single line of server code:
- Will more than one client or agent use this? If no, skip MCP.
- Is there already a CLI that does it? If yes, let the agent run the CLI.
- Is it a one-off integration for one project? Write a local tool, not a server.
- Do you need it to outlive this repo and be shared? Now MCP makes sense.
Notice how often the answer is "skip MCP." For a solo builder shipping one product, it's almost always skip. You don't have many clients. You have one. You're building infrastructure for a fleet you don't own.
The wrapper trap
The most common bad MCP server is the API wrapper. Someone takes a REST API that's already well-documented, already has an OpenAPI spec, already works with a bearer token, and wraps it in MCP. Why? The agent could read the spec. It could make the request. You've added a translation layer between the model and a thing the model was already good at.
Worse, you've now hidden the API's actual surface behind your hand-picked tool definitions. The API has 40 endpoints. Your server exposes 6, because those were the ones you needed Tuesday. Now the agent literally cannot do the other 34 things without you shipping a new server version.
If the underlying thing is an HTTP API, try this first:
# Let the agent just call it
curl -s https://api.example.com/v1/items \
-H "Authorization: Bearer $TOKEN" | jq '.items'
Give the model the base URL, the auth pattern, and the docs. Watch it work. You'll be shocked how often the "we need an MCP server" requirement evaporates.
When I do reach for MCP
I'm not anti-MCP. I built one for a vector store that four separate agents query, with shared embedding logic I did not want to reimplement four times. That's the sweet spot: real shared state, real multi-consumer, real cost to duplicating the logic. The protocol earned its place.
I also use it when the capability needs to be stateful in a way a stateless CLI can't manage well — a long-lived connection pool, a cached index, an auth session that's expensive to re-establish. The server holds the state. The agents borrow it. Good fit.
But those are specific. They're not "every integration." The default should be: direct tool, or CLI, or a plain function. MCP is the escalation, not the starting point.
The resume-driven development problem
Let's be real about why this happens. MCP is new and hot, and "built an MCP server" sounds better in a standup than "wrote a 12-line tool definition." I get it. The incentive is to build the impressive-sounding thing.
But your users don't care about your architecture. They care whether the agent ships the feature. Every hour you spend building protocol plumbing for a single-consumer integration is an hour you didn't spend on the product. The most senior move is often the boring one: skip the server, call the API, move on.
Build the MCP server when you have many mouths to feed. Until then, your agent has a shell. Let it use it.
