Do you need an MCP server, or just function calling?
MCP got enough attention in 2025 and 2026 that the question inside a lot of engineering teams has flipped from "what is it?" to "should every tool be an MCP server?" The honest answer is no. MCP and function calling are not competitors, and treating the choice as a versus is where teams waste a week building a server they did not need. Function calling is how the model asks to do something. MCP is a standard way to expose the thing it wants to do. The real decision is not which one to use but whether a given capability deserves to live behind a standalone server or should stay inline in your app.
- Function calling is the model API: the LLM emits a structured request, your code executes it, and the tool schemas travel with each request, coupled to your app and provider.
- MCP is an integration layer above that: a server exposes tools over a standard protocol so any MCP client can discover and call them, decoupled from any single app or model.
- Build an MCP server when a capability is shared across clients or models. Keep function calling when the tool is app-specific, latency-sensitive, dynamic, or still being prototyped.
What each layer actually does
Function calling is a feature of the model API. You send the model a list of tool schemas, it responds with a structured request to call one, your code runs it, and you feed the result back. The tool definitions are just data you pass on every request, which means they live in your application and are shaped to your provider's format. That coupling is fine when the tool belongs to one app and one model.
MCP sits one level up. An MCP server exposes tools, resources, and prompts over a defined protocol and a transport, and any MCP-compatible client can connect, discover what is available, and call it. The client still uses function calling under the hood to let the model express intent; MCP is what carries that intent to a server that executes it. The point of the extra layer is decoupling: the same server works across different apps and different models without you rewriting the tool for each one.
Build an MCP server when the capability is shared
The clearest reason to stand up a server is reuse across clients. If the same capability, say querying your production database or searching internal docs, needs to work inside a desktop assistant, an IDE, a Slack bot, and an automated pipeline, function calling forces you to redefine and re-implement that tool in every one of them. An MCP server lets you build the tool once, run one service, and connect many clients to it. That is a real maintenance win the moment a second consumer appears.
Multi-model portability is the second reason. An MCP server works with any MCP client regardless of which model powers it, so your tools are not locked to one provider's function-calling format. When you switch or mix models, the tools keep working without a rewrite. The third reason is governance: when a capability touches sensitive systems and should be owned, versioned, and access-controlled by a platform team rather than copied into every product, a server gives you one place to manage it. These are the same forces that justify pulling any shared capability out of an app and into a service.
Stay with function calling when the tool is local
Plenty of tools should never become servers. If a tool is used by exactly one application, wrapping it in MCP adds a process and a network hop for zero reuse benefit. Keep it inline.
Latency-sensitive paths are another case. Function calling executes within your app; MCP adds a hop to a separate server, and on a path where every millisecond counts that overhead can outweigh the portability. Dynamic tools are a third: some tools are generated at runtime from the current context, and function calling handles that naturally because the schemas are just data you pass per request, while an MCP server expects a more stable catalog. And when you are still prototyping, testing whether a tool is even useful, inline function calling lets you iterate without standing up infrastructure. Graduate it to a server later if it proves worth sharing. The same instinct that governs designing the tools themselves applies here: start simple, add structure only when the reuse is real.
The cost of the extra hop
An MCP server is not free once you build it. It introduces a process and network boundary, which means a new set of failure modes: the server can be down, slow, or return malformed responses in ways an inline function call never could. Those failures show up specifically under agent load, which is why an MCP server that passes manual tests can still fail in agents. The boundary is also a security surface. A server that exposes tools to multiple clients needs real authentication and authorization, because "any client can connect and discover tools" is a feature you have to gate deliberately, not a default you want open. Tool inputs crossing that boundary also widen the prompt injection surface, since a compromised or malicious client can drive the tools you exposed.
None of this argues against MCP. It argues for building a server when the reuse, portability, or governance benefit is large enough to pay for the reliability and security work the boundary demands, and not before.
The pattern most teams land on
In practice most teams end up mixed rather than all-in on either side. Tools that are tightly coupled to a single app stay as function calling. Capabilities that represent shared building blocks, querying databases, searching docs, calling internal APIs, managing infrastructure, move to MCP servers where several clients and models can reuse them. A useful default is to start every tool as an inline function call and graduate it to a server the day a second consumer shows up. That keeps prototypes fast and reserves the extra infrastructure for the tools that have earned it. For a small team weighing the tradeoff, our note on MCP servers for startups walks through when the investment pays off at that stage.
Frequently asked questions
Is MCP a replacement for function calling?
No. They operate at different layers and work together. Function calling is how the model expresses that it wants to use a tool; MCP is a standard way to expose and execute that tool across clients and models. An MCP-based setup still relies on function calling underneath. The choice is not one or the other but whether a specific tool lives inline in your app or behind a shared server.
Does an MCP server add latency?
Yes, some. An inline function call runs inside your application; an MCP call crosses a process or network boundary to a separate server. For most tools that overhead is negligible next to the model's own generation time, but on latency-critical paths it can matter enough to keep the tool inline. Measure it on the path in question rather than assuming.
When is it too early to build an MCP server?
While a tool has exactly one consumer and you are still deciding whether it is useful. Standing up a server, a transport, auth, and versioning for a single-app tool that might get deleted next week is wasted infrastructure. Keep it as an inline function call, and convert it the moment a second client or a second model needs the same capability.
Can I mix MCP servers and inline function calling in one app?
Yes, and most production systems do. Shared, governed capabilities live behind MCP servers while app-specific or dynamically generated tools stay as inline function calls in the same application. The model sees a unified set of tools to call; where each one executes is an architecture decision you make per tool, not a single choice for the whole app.
Rather we just build it?
Book a free scoping call and we'll ship your production-safe AI feature this week.