Model Context Protocol (MCP) is one of the most useful ideas to hit the LLM tooling space in a long time. It gives us a common way to connect models to tools, data, and systems without inventing a fresh integration pattern every week. That is the good news. The bad news is that MCP also makes it much easier to wire LLMs into real systems before a team has earned the operational discipline to do that safely. We can now connect a model to databases, filesystems, an issue tracker, a shell, or a production API with startling ease. That power is real. But so is the blast radius.
MCP's popularity forces us to ask: Does MCP really need to be used for every use case? For instance, a local single-user workflow may still be better served by a direct CLI or API. But once the interface itself needs to be standardized across clients, MCP becomes something broader than a tool wrapper. The protocol standardizes not only tools, but also prompts and resources, and it supports both local stdio servers and remote Streamable HTTP deployments with very different operational shapes. Once MCP becomes that shared surface, ordinary engineering mistakes don't stay ordinary for very long.
That distinction matters even more now that MCP has become part of the strategy for API gateways, integration platforms, and automation vendors. They can add useful features to an existing system: authentication, rate limits, proxying, logging, governance, and catalog management. None of that is bad. But none of it changes the quality of the capability being exposed. A bad API does not become a good model-facing capability just because it now speaks MCP. If the backend contract is over-broad, vague, unstable, or noisy, the gateway may make it easier to distribute, but it does not make it safer to trust.
This is important to realize because neither MCP nor enterprise platforms for APIs create bad engineering instincts. A vague thrown error that used to annoy one developer can now confuse every user of an assistant. A credential that was already too broad becomes more dangerous once it sits behind a tool the model can invoke autonomously. An oversized response that is merely inefficient in a local script becomes a cost and latency issue when it is sent to a model repeatedly. The protocol is not the villain here. The combination of convenience, power, and underdeveloped discipline is.
When I think about the most common implementation problems in MCP systems, I do not think of them first as bug categories. Instead, I think of them as engineering impulses. The bug you see popping up in production is the symptom. The deeper problem is the instinct that made the bug feel reasonable in the first place. We act on them often enough, casually enough, and confidently enough that we stop noticing the harm. They start to feel normal. Mundane, even.
"We see a deadly sin on every street corner, in every home, and we tolerate it. We tolerate it because it's common, it's trivial."
This is what John Doe, the main antagonist of the classic movie Seven, says near the end of the film. I think the same thing happens in software engineering. We return too much data. We ask for too many permissions. We hide bad errors behind vague ones. We add one more tool, one more abstraction, one more shortcut. None of it feels dramatic in the moment, which is exactly why these habits survive.
That is why I like to think of these engineering impulses as deadly sins. Some of them even straddle more than one sin. A symlink traversal bug is both excessive access and unsafe system intimacy. A retry storm is both operational instability and resource abuse. A bloated tool payload is both gluttony and a symptom of prideful design. The categories are not airtight boundaries, but they are useful. They help us distinguish between sins that expand the blast radius, sins that cause live systems to fail badly, and sins that quietly make the whole product harder to trust.
In this series, I will discuss examples from three sources: a recent MCP fault taxonomy paper that analyzed hundreds of issues across public repositories, public GitHub issues and security advisories, and mistakes of my own. I have shipped versions of several of these sins too: over-broad scope, vague errors, and overly helpful responses that returned far more than the task needed. Taken together, they paint a practical picture of how MCP systems actually go wrong. This is not a theoretical taxonomy built in a vacuum. It is a set of recurring failure modes that keep showing up where real teams are trying to ship real systems.
The seven deadly sins are the framework I will use to make those impulses easier to see before they harden into architecture.
| Sin | Meaning | Example |
|---|---|---|
| Lust | Too much intimacy. | A tool for checking container status accepts arbitrary shell input, turning a simple operational check into command execution. |
| Greed | Too much power. | A read-only code review assistant is given a GitHub token that can also push commits, merge PRs, and manage secrets. |
| Sloth | Too little care. | An expense lookup fails with request failed, leaving finance unable to tell whether the report ID was invalid or the service timed out. |
| Wrath | Too much force. | A timeout in a background sync causes the client to resubmit the same job every second until the queue backs up. |
| Gluttony | Too much. | A calendar tool returns the full event body, attendee list, history, and notes when the user only asks for the next meeting. |
| Pride | Too much ego. | A homegrown tool framework auto-coerces inputs behind the scenes, and a deploy tool starts failing in ways nobody can explain quickly. |
| Envy | Too much imitation. | A team adds three overlapping issue-creation tools because other servers have big catalogs, and the model keeps picking the wrong one. |
These seven sins are not equally dangerous at all times. Some create an immediate blast radius. Others quietly compound costs, confusion, or maintenance burdens until the system becomes too expensive to trust. That is why this series is ordered the way it is.
How this series is organized
This series is written for people designing, reviewing, or operating MCP systems in production, so I organized the deadly sins into categories because that is usually how remediation work gets sequenced in practice. Security Sins covers Lust and Greed, the sins that decide blast radius by defining what the model can reach and what authority it carries there. Operational Sins covers Sloth and Wrath, the sins that decide whether the system fails truthfully and under control once it is live. Design Sins covers Gluttony, Pride, and Envy, the slower sins that compound cost, ambiguity, and maintenance burden even when they do not explode first.
Throughout the series, I am talking about MCP as a protocol surface, not just a codebase full of handlers. Some sins show up in tools. Some show up in prompts and resources. Some show up in transport choices, and some in the authorization and policy boundary around the whole system.
The final part, Road to Redemption, shifts from recognition to practice. That is where the series turns into refactoring order, review questions, metrics, and the habits that keep these sins from settling back into the architecture. So this is not just a list of problems. It is a way to decide what to fix first, what to review with more skepticism, and what to treat as a design smell before it becomes a production problem.
Top comments (0)