When You Don't Need MCP A developer explains when Model Context Protocol (MCP) is unnecessary, comparing it with alternatives like function calling and CLI tools. The post highlights that MCP introduces context overhead and server resource consumption, and notes that models see no difference between MCP and function calling. Most tutorials you'll come across explain what MCP is and why you should use it. After all that explanation, it's still hard to get an intuitive feel for the trade-offs. So today I'll flip the question around: when do you not need MCP? That's a better way to build intuition about it. MCP Model Context Protocol is an open protocol launched by Anthropic that lets AI applications agents like Claude Code, Claude Desktop, OpenClaw discover and call external tools, and read external resources, in a unified way . That's the textbook definition. In practice, you can think of MCP as a kind of resource exposed to an agent. Before MCP existed, if you wanted an AI application to connect to services like Google Drive, GitHub, or Slack, every single AI application had to write its own integration code for every external service. MCP is essentially a "standard socket" defined for that connection. If you skip MCP, you still have plenty of other options. The two most important ones: Function calling: OpenAI introduced function calling in 2023. It's actually simple — you pass a function signature to the LLM first. { "name": "get weather", "description": "Get the current weather for a specified city", "input schema": { ... "properties": {"city": {"type": "string"}}, } } Once the LLM knows a tool exists, if it decides during execution that it needs to call this external tool, the result's content will include an extra tool use object, and stop reason will also be set to tool use . Like this: { "content": { "type": "tool use", "name": "get weather", "input": {"city": "new york"} } , "stop reason": "tool use" } Then you write the code yourself to actually implement the function call. if response.stop reason == "tool use": tool use = response.content -1 // ... call the weather-lookup function In real-world work it's obviously less crude than this — you'd use a framework like LangChain. CLI: This is really just another form of function calling — except you expose exactly one tool, and you tell the LLM upfront that it's a bash shell, so it can write whatever command it wants. The advantage is you don't need to tell the LLM what bash can do or how to use it — the LLM has already read enough material to know how to write bash commands on its own. But using a CLI comes with real risk, since permission control is hard to get right. First, you need to understand one thing: the model has no idea whether you're calling it through MCP or through function calling. For example, when you register a weather-lookup tool, if you register it via MCP, here's what the model sees in its tools list: { "name": "get weather", "description": "Get the current weather for a specified city", "input schema": { "type": "object", "properties": { "city": {"type": "string"} } } } If you use function calling instead, here's what the model sees: { "name": "get weather", "description": "Get the current weather for a specified city", "input schema": { "type": "object", "properties": { "city": {"type": "string"} } } } Let's play a little game: can you spot the difference between these two JSON blocks? The answer is there isn't one. So there's no need to agonize over whether MCP versus function calling affects the model somehow. As far as the model is concerned, there's no difference at all. If MCP is so great, why not just use it everywhere? Because MCP does have real downsides: Large context overhead: Once you connect to an MCP server, the full schema name, parameters, description for every tool that server exposes gets stuffed into the model's context window up front — whether or not this particular conversation ever needs it. Server resource consumption: An MCP server is something that runs continuously and has to stay alive. The more MCP servers you spin up, the more CPU and memory they eat on your machine. Operational burden: Since an MCP server is a separate process, you're on the hook for restarting it when it crashes, sequencing startup order across multiple servers, and maintaining internal state over time. MCP sounds pretty rough so far. So why do so many companies keep using it anyway? Because despite its downsides, its biggest strength is unifying the integration interface across your project's resources. A unified interface brings two benefits on its own: Cleaner calling code: People who don't build software won't really feel this benefit, but anyone who does knows immediately how good a unified interface is. Your thousands of lines of legacy spaghetti code can suddenly collapse into a dozen lines. The more interfaces you have, the more bugs get buried, and buried deeper — maintenance becomes endless. Easier third-party integration: Once every third-party resource is packaged as MCP, integrating them no longer takes a lot of custom effort. There's nothing technically clever about this — it's the same idea as standardizing currency or units of measurement. What matters is that someone has to actually go do it. If your situation matches one of the following: then MCP is worth considering. Otherwise, a lighter-weight approach — like plain function calling — is enough. I'm CodePlato. I believe human creativity is the true tree of AI Coding. Code and models are only shadows projected onto the walls of the cave. X: @codeplato2026 https://x.com/codeplato2026 https://x.com/codeplato2026