"Should we use MCP or function calling?" is one of the most common questions in tool-use discussions, and it is a category error. It is like asking whether to use HTTP or JSON. The two solve different problems at different layers, and in a typical 2026 stack you use both at once, usually without thinking about it.

This piece untangles the layers. For the full protocol picture, start with what MCP actually is, the pillar of this cluster. The neighboring articles cover how to design a good server, the security implications, and which servers are actually worth running.

Function calling: a shape inside one API call

Function calling (OpenAI's original name; Anthropic calls it tool use) is a convention inside a single LLM API request. You send the model a list of function definitions — name, description, JSON Schema for arguments — alongside the conversation. If the model decides a function would help, it responds not with prose but with a structured call: a function name and arguments. Your code executes that call however it likes, appends the result to the conversation, and calls the API again. The model reads the result and continues.

That is the whole mechanism. Three properties follow from it:

It is stateless. Every API call carries the full list of available functions. The model has no memory of tools between requests beyond what is in the conversation, and nothing outside the request can signal that anything changed.

It is undiscoverable. The model can only see functions you explicitly passed in. Where those definitions came from — hardcoded, config file, another process — is entirely your problem. The API has no concept of "go find out what tools exist."

It is execution-agnostic. The API standardizes how the model asks for a call and how you report the result. What happens in between — the actual work — is invisible to it.

These are not flaws. Function calling is deliberately minimal, and every major provider (OpenAI, Anthropic, Google, Mistral) converged on essentially this shape by 2024 because it is the right minimal shape. But minimal means everything around it is left to you.

MCP: the protocol around the loop

MCP addresses exactly the parts function calling leaves open: where tool definitions come from, how the process implementing them is reached, and how state is shared over time. It is a client-server protocol — JSON-RPC over a transport — and three of its properties are things function calling structurally cannot have.

Discovery. An MCP client enumerates what is available at runtime. Connect to a server, call tools/list, get back every tool with its schema. Same for resources and prompt templates. Point your client at a new server and its capabilities appear without a line of integration code. With bare function calling, adding a tool means editing the application.

A live counterpart. An MCP connection begins with an initialization handshake and negotiated capabilities. As of the 2026-07 spec release candidate the protocol layer itself is stateless — session state is managed at the application level — but the server can still send messages while it is processing a client request: the tool list changed, a resource was updated, here is progress on a long-running operation. Function calling has no channel for any of this — nothing on the other side can speak until the next request, because there is no "other side," only your own code.

Transport. MCP defines how the bytes move. Local servers run over stdio — the client spawns the server as a subprocess, which is why installing a local MCP server is usually one line of config. Remote servers use HTTP: the original November 2024 spec paired HTTP with server-sent events for the return direction, and the 2025 spec revisions replaced that with streamable HTTP, a cleaner single-endpoint design that sits happily behind ordinary load balancers. As of mid-2026, streamable HTTP is the standard remote transport.

Notice the model has appeared nowhere in this section. That is the point: MCP is a protocol between the client application and tool servers. The model never speaks it.

How they compose

Here is the full loop in a real 2026 client, say an IDE assistant with a GitHub MCP server configured:

  1. At startup, the client launches (or connects to) the server and calls tools/list over MCP. It gets back create_issue, list_pull_requests, and friends, each with a description and schema.
  2. When you start a conversation, the client translates those MCP tool definitions into the model provider's function-calling format and includes them in the API request. To the model, they are indistinguishable from hardcoded functions.
  3. The model emits a function call: create_issue with a title and body.
  4. The client routes that call over MCP to the server (tools/call), the server hits the GitHub API, and the result travels back.
  5. The client appends the result to the conversation and re-invokes the model, which continues in prose.

MCP handles steps 1, 4, and the plumbing; function calling handles steps 2, 3, and 5. Remove MCP and the loop still works — you just write and register every integration by hand, per client. Remove function calling and MCP has no way to let the model trigger anything. Complements, not competitors.

One practical consequence: since MCP tool descriptions are injected straight into the model's context as function definitions, a server effectively writes part of your prompt. A well-designed server writes descriptions the model can act on reliably — covered in server design basics — and a malicious one can inject instructions through the same channel, which is a headline risk in security considerations.

When each layer is the answer

If you are building a closed application with three fixed internal tools and one model provider, bare function calling is fine. The definitions live next to the code that implements them, nothing is dynamic, and a protocol layer would be ceremony.

MCP earns its keep when any of these are true: multiple clients need the same integrations; you want integrations someone else already built (the ecosystem of existing servers is the practical selling point); tools need to come and go at runtime; or the tool implementation should live in a different process or on a different machine, with its own credentials, than the model loop. By mid-2026 most non-trivial setups tick at least two of those boxes, which is why the default has flipped from "hand-wire functions" to "connect servers."

The takeaway

Function calling is the request/response shape inside a single model API call: the model asks, you execute, you report back. MCP is the protocol underneath that determines where those functions come from, how the processes providing them are reached over stdio or streamable HTTP, and how capabilities are discovered and negotiated — state itself, as of the 2026-07 spec release candidate, lives at the application level rather than in the protocol. One is a grammar the model speaks; the other is infrastructure the client speaks. Stop choosing between them — in practice, you are almost certainly going to use both, in that order.