
ArticleaiDeep read
The Real Difference Between MCP, Function Calling, and Agent Loops
BitByteCore AI DeskAug 5, 20263 min
They're not competitors — they're three layers of one system. Function calling is what the model emits, MCP is how tools reach it, and the agent loop is what keeps it running. Confuse them and you'll spend an afternoon debugging the wrong layer.
A deep read — the full picture, with the receipts.
Smart engineers mix up MCP, function calling, and agent loops for a good reason: all three show up at the same moment — the instant a language model stops talking and tries to do something in the outside world. But they aren't competing options, and they aren't three names for one idea. They're three different layers of the same system, and each answers a different question.
- Function calling is what the model emits — a structured request to run something.
- MCP is how a tool reaches the model — a standard plug between your app and the systems that hold the tools.
- The agent loop is what keeps the whole thing running — the code that calls the model, executes what it asked for, feeds back the result, and decides when to stop.
Get these straight and most "why is my agent doing that?" bugs sort themselves into a layer. Confuse them and you'll spend an afternoon patching the loop when the real problem was your tool schema.
Function Calling: What the Model Actually Does#
Function calling (some providers call it tool use) is a structured output format. You hand the model — Claude Opus 4.8, GPT-5.5, Gemini 3.1 Pro, whichever — a list of available functions, each with a name, a description, and a JSON Schema for its arguments. Instead of only replying in prose, the model can now reply with a machine-readable request to invoke one of them.
The single most important thing to understand: the model does not run anything. It emits a request. Your code runs the function. The model just fills in the blank with "here's what I'd like called, and with these arguments."
A response with a tool call looks roughly like this (Anthropic's shape):
{
"stop_reason": "tool_use",
"content": [
{ "type": "text", "text": "Let me look that up." },
{
"type": "tool_use",
"id": "toolu_01A9...",
"name": "get_weather",
"input": { "city": "New York", "unit": "celsius" }
}
]
}
Every provider wraps the same idea in a slightly different envelope. OpenAI returns a tool_calls array where the arguments arrive as a JSON string you have to parse yourself; Google's Gemini uses a functionCall part with an args object; Anthropic uses the tool_use block above. The concept is identical — the model names a function and supplies arguments — but the field names, the ID scheme, and how you hand the result back all differ. Papering over exactly these differences is most of what a tool-calling library does for you.
That's the whole layer. Function calling is local to a single model response. No network protocol, no orchestration — just "the model asked to run something, in a format you can parse."
MCP: The Protocol Layer Nobody Drew a Box Around#
MCP is the Model Context Protocol, an open standard Anthropic released in November 2024 and later handed to neutral governance as it caught on. The problem it solves is boring and enormous: before MCP, every tool integration was bespoke. If you had N AI apps and M tools (GitHub, Postgres, your internal API), you were on the hook for roughly N × M custom integrations, each re-implemented per app. MCP turns that into N + M: build a server once, and any MCP-compatible app can use it. Anthropic's own analogy — "USB-C for AI" — is the right one. It's a standard plug.
MCP defines three roles, and this is where most explanations (including earlier drafts of this one) get it backwards:
- Host — the AI application you're actually using. Claude Desktop, an IDE like Cursor, a customer-support agent you built. The host runs the model interaction and manages one or more clients.
- Client — a connector living inside the host that keeps a dedicated one-to-one session with a single server. One server, one client.
- Server — a separate program that exposes capabilities. This is the part people build and share: a GitHub server, a filesystem server, a database server. It runs locally as a subprocess or remotely as a web service.
The transport between client and server is one of two things:
- stdio — the host launches the server as a child process and talks to it over standard input/output. Simple, fast, local. Still the most common setup.
- Streamable HTTP — JSON-RPC 2.0 over a single HTTP endpoint, with optional Server-Sent Events for streaming. This is what you use for remote servers. It replaced the older HTTP+SSE transport, which is now deprecated — if a tutorial tells you to stand up two separate SSE endpoints, it's out of date.
And a server exposes three kinds of things — worth memorizing, because they're routinely confused:
- Tools — functions the model decides to call (send an email, run a query). Model-controlled.
- Resources — data the server makes available as context: file contents, a database schema, an API response. Application-controlled — the host decides what to pull in, and resources are meant to be side-effect-free reads, closer to a GET endpoint than an action. (A resource is data for context, not an API key or a credential — secrets live in the server's config, never exposed as a resource.)
- Prompts — reusable, parameterized templates a user invokes deliberately, like a slash-command workflow. User-controlled.
Here's the part that dissolves the MCP-vs-function-calling confusion: MCP does not replace function calling — it feeds it. An MCP server advertises its tools; the host lists them; those tools are handed to the model as ordinary function-calling tools. When the model emits a tool call, the host routes it through the MCP client to the right server, gets the result, and returns it. Function calling is still the mechanism. MCP is the standardized wiring that gets tools to that mechanism and results back — without you writing a custom adapter per tool, per app.
The Agent Loop: The Runtime That Drives Everything Else#
Function calling gets you one round trip: the model asks, you answer. An agent loop is what turns that single exchange into work that finishes on its own. It's the control flow that repeatedly calls the model, runs whatever tools it asks for, feeds the outcomes back, and continues until the task is actually done.
Stripped to its bones:
messages = [user_request]
while True:
response = model.generate(messages, tools=available_tools)
messages.append(response)
if not response.tool_calls: # model replied in plain prose
break # -> the task is finished
for call in response.tool_calls:
result = execute(call) # run the tool; catch and report errors
messages.append(result) # feed the outcome back into context
# loop: the model now sees the results and decides the next move
The shape is plan → act → observe, repeated. The model plans (which tool, which arguments), your code acts (runs it), and the result is observed by appending it to the conversation so the next model call can react. Each turn, the context grows with everything that happened — that is literally how the model "remembers" what it already tried.
Almost everything hard about agents lives in this loop, and none of it is the model's job:
- Termination.
while Trueis a promise to loop forever. Real loops stop on an explicit "done" signal, a max-iteration cap, a token/cost budget, or a wall-clock timeout. Miss this and a confused model bills you in circles. - Error handling. When a tool throws, you decide whether to feed the error back so the model can retry differently, or to abort. A stack trace returned as a tool result is often enough for the model to correct itself on the next turn.
- Context management. Long tasks overflow the context window. Trimming, summarizing, or offloading to external memory is loop-level work.
- Guardrails. Approval gates before destructive actions, allow-lists on which tools can fire — this is where you enforce them.
This is the layer you own. The model and MCP are largely handed to you; the loop is your application, and its quality is most of what separates a demo from something you'd let touch production.
Where the Layers Intersect (and Where Bugs Hide)#
Stacked up, one request flows like this:
Agent loop ── owns the control flow: keep going until the task is done
│
├─ calls ─▶ The model ── emits a function call: {"name": "...", "input": {...}}
│ (function calling = the model's request format)
│
├─ routes the call ─▶ MCP (optional) ── standard plug from host to an
│ external server exposing tools / resources / prompts
│
└─ executes ─▶ the real world: an API, a file, a database, a shell
└─ result flows back ─▶ appended to context ─▶ loop again
Or as a table:
Notice that MCP is the optional layer. You can run a perfectly good agent loop with hand-wired tools and no MCP at all — plenty of production systems do. MCP earns its place when you want the same tools reused across apps, or want to drop in third-party servers without writing an adapter each time.
Knowing the layers tells you where to look when something breaks:
- The model calls the wrong tool, or hallucinates arguments. That's a function-calling problem — usually a vague tool description or a loose schema. Fix the tool definition, not the loop.
- The tool never fires, or the result comes back mangled. That's a wiring problem — a broken MCP transport, a server that crashed, a result serialized wrong.
- Every step works but the task never finishes, loops forever, or quits early. That's an agent-loop problem — your termination logic, your error handling, your context management.
Most painful agent bugs are really someone debugging the wrong layer: rewriting prompts to fix what is actually a broken loop, or reworking orchestration to fix what is actually a sloppy tool schema.
Framework Reality Check: MCP in Mid-2026#
When MCP shipped in late 2024, the open question was whether anyone besides Anthropic would use it. That question is closed. Through 2025 it was adopted by OpenAI (the Agents SDK, the Responses API, and ChatGPT), Google DeepMind (Gemini and its agent SDK), Microsoft, and AWS, and it moved under neutral governance at the Linux Foundation. In 2026, "does it speak MCP" is table stakes, not a differentiator.
So the useful question isn't whether a framework supports MCP — most now do, natively or through an adapter — but how it runs the loop and how much of it you have to build yourself:
- LangChain / LangGraph connect to MCP servers through adapters and expose the tools as ordinary tools; LangGraph is the piece that gives you an explicit, inspectable loop modeled as a state graph.
- LlamaIndex stays data- and retrieval-first, and can pull MCP tools into its agent abstractions.
- CrewAI organizes work as roles and tasks across multiple agents, and can consume MCP tool servers.
- OpenAI's Agents SDK treats MCP as a first-class way to attach tools and runs the loop for you.
The differences that actually matter in practice: whether MCP support is native or bolted on with an adapter, how much of the agent loop the framework hides versus lets you control, and how it handles the unglamorous parts — retries, streaming, human-in-the-loop approval. Those, not a support checkbox, are what you're choosing between.
Decision Guide: Which Layer Do You Actually Need?#
These aren't mutually exclusive — a serious agent uses all three at once. The real question is how much machinery a given job justifies:
- One tool, one call, one app. Plain function calling. Define the tool, parse the response, run it, return the answer. Don't stand up an MCP server or a loop for a single round trip.
- The same tools across several apps or models — or third-party tools you'd rather not hand-integrate. Reach for MCP. Build or install a server once and let every compatible host use it. The payoff is reuse and standardization; skip it for a genuine one-off.
- A multi-step task the model has to work through on its own — call a tool, react to the result, decide the next move. You need an agent loop, with real termination conditions, error handling, and guardrails. This is where reliability is won or lost, so build it deliberately rather than copying a
while Truefrom a demo.
The failure mode at each end is symmetrical: wrap a single lookup in a full agent framework and you've over-engineered it; try to run a ten-step workflow through one function call and you've under-built it. Name the layer the job actually needs, and both mistakes disappear.
Sources
- Model Context Protocol — specification (2025-11-25)modelcontextprotocol.io
- Model Context Protocol — what MCP ismodelcontextprotocol.io
- Anthropic — Tool use with Claude (Claude Platform docs)platform.claude.com
- OpenAI — Function calling (API guide)developers.openai.com



Discussion