|
| 1 | +--- |
| 2 | +slug: mcp-servers-nightmare |
| 3 | +title: MCP servers are a nightmare for engineers |
| 4 | +tags: [mcp, servers, scalability, authentication, engineering, tool-calling] |
| 5 | +--- |
| 6 | + |
| 7 | +# MCP servers are a nightmare for engineers |
| 8 | + |
| 9 | +> *"If you have more than five tools, an MCP rollout feels like spawning a new micro-service for **every** function call. We ended up with 40 tiny servers, 40 sets of secrets, and one giant Ops headache."* |
| 10 | +> — *Engineering team at a Series B startup* |
| 11 | +
|
| 12 | +MCP (Model Context Protocol) was supposed to "standardise tool calling for LLMs." Instead it created a forest of mini-services that crumble under real-world scale and expose brand-new security holes. Here's why production teams are quietly ripping MCP back out of their stacks. |
| 13 | + |
| 14 | +<!--truncate--> |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## 1. One API ⇒ One MCP server ⇒ One scaling nightmare |
| 19 | + |
| 20 | +**Design flaw:** Every tool definition lives behind its own long-running MCP server. A project with 20 tools is now a 20-service deployment. Horizontal scaling becomes a Knuthian combinatorial explosion: |
| 21 | + |
| 22 | +```yaml |
| 23 | +# naïve K8s layout |
| 24 | +weather-mcp × N replicas |
| 25 | +db-mcp × N replicas |
| 26 | +payment-mcp × N replicas |
| 27 | +# ... and so on |
| 28 | +``` |
| 29 | + |
| 30 | +* **Orchestration overhead:** service discovery, health checks, autoscaling rules, and CI/CD pipelines multiply linearly. |
| 31 | +* **Resource thrash:** idle MCP servers still hold sockets and memory; at peak they compete for the same CPU shares. |
| 32 | +* **Cold-start pain:** spawning a new server per customer or per tenant means hundreds of containers during load spikes — exactly the kind of burst K8s is slowest to absorb. |
| 33 | + |
| 34 | +Even MCP contributors admit that "one server per API sounds crazy if you're doing backend" after wrestling with dozens of them in production. |
| 35 | + |
| 36 | +--- |
| 37 | + |
| 38 | +## 2. “Bring-your-own-auth” is a security trap |
| 39 | + |
| 40 | +The spec punts on authentication, so every vendor rolled their own: |
| 41 | + |
| 42 | +* **OAuth, mutual-TLS, Static tokens,** or — far too often — **nothing at all.** Engineers joke that "the S in MCP stands for Security" precisely because it doesn't. |
| 43 | +* **Key-store of doom:** each server needs credentials for the upstream tool *and* for the calling agent. When one leaks, the blast radius includes *every* downstream service accessible through that server. Hackers love a single vault full of all your API keys. |
| 44 | +* **Proven attack vectors:** MCP servers often run with elevated privileges and expose additional attack surface through their custom authentication mechanisms. |
| 45 | + |
| 46 | +The security model fundamentally breaks down when you have dozens of independent servers, each implementing their own auth patterns. |
| 47 | + |
| 48 | +--- |
| 49 | + |
| 50 | +## 3. Debugging distributed auth failures, not latency numbers |
| 51 | + |
| 52 | +Latency is fixable with caches; **broken auth flows** cascade: |
| 53 | + |
| 54 | +1. Token refresh fails in one MCP server. |
| 55 | +2. All agents routed to that pod get 401s. |
| 56 | +3. Autoscaler spawns more replicas of the *broken* image. |
| 57 | +4. Your incident channel fills with “tool unavailable” alerts while dashboards stay green (the servers are *up*, just unauthorised). |
| 58 | + |
| 59 | +Tracing the root cause means correlating logs across **agent → client SDK → MCP server → tool → identity provider**. That’s five codebases, often in five languages. |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## 4. MCP locks you *out* of real scaling patterns |
| 64 | + |
| 65 | +MCP’s JSON-RPC-over-stdio/HTTP tunnel ignores native features of the protocols it proxies: |
| 66 | + |
| 67 | +* **WebSockets & streaming gRPC**: forced back into polling loops; throughput nose-dives when messages surge. |
| 68 | +* **Binary blobs**: base64 inflation wrecks memory-bandwidth-sensitive workloads (vision, audio). |
| 69 | +* **Fan-out fan-in patterns**: you still need a coordinator outside MCP, defeating its “single interface” pitch. |
| 70 | + |
| 71 | +Teams building high-frequency trading bots reported a 20× drop in tick rate once they moved feeds through MCP. |
| 72 | + |
| 73 | +--- |
| 74 | + |
| 75 | +## A labyrinth of servers |
| 76 | + |
| 77 | +If you've already tackled the operational complexity listed above and think MCP servers are a good investment of your engineering time, go ahead — just make sure to budget for the maintenance work that's inevitably needed. Another option is to adopt existing MCP server frameworks and accept the architectural trade-offs. |
| 78 | + |
| 79 | +To solve this problem at scale, we've been experimenting with a more boring approach: **UTCP (Universal Tool Calling Protocol)**. The idea is simple: let your agents speak the tool's native protocol directly, without a proxy layer. |
| 80 | + |
| 81 | +The architecture is much less interesting: tools are just API definitions, calls go direct to the service, and you reuse whatever auth infrastructure you already have. It scales like any stateless API because that's exactly what it is. |
| 82 | + |
| 83 | +--- |
| 84 | + |
| 85 | +### Bottom line |
| 86 | + |
| 87 | +**MCP is great for what it was designed for:** sharing prompts, resources, and context between AI systems. When you need to give an LLM access to your company knowledge base or standardize prompt templates, MCP shines. |
| 88 | + |
| 89 | +**But tool calling? That's where MCP becomes a nightmare.** |
| 90 | + |
| 91 | +Forcing every API call through a JSON-RPC proxy server turns simple HTTP requests into distributed systems nightmares. You end up with **microservices-sprawl-as-a-spec** combined with DIY security theatre. If your architecture already struggles with too many services and secrets, MCP's tool calling approach adds gasoline to the fire. |
| 92 | + |
| 93 | +For tool calling, the fastest fix is the simplest: delete the proxy, call the API directly. |
0 commit comments