Function Calling vs MCP: How AI Agents Call Tools
Function calling lets a model request a tool call within one API request; MCP is a protocol for exposing whole toolservers that many models can share.
Function calling is a model capability — the ability for an LLM to output a structured request to invoke a specific function, defined per-request by whoever is calling the API. The Model Context Protocol (MCP) is a standardized, transport-level protocol for exposing a whole server’s worth of tools, resources, and prompts to any compliant client, independent of which model is on the other end. They’re not competitors so much as different layers of the same stack: MCP is commonly implemented on top of an underlying function-calling mechanism.
Function calling: a per-request capability
When you use function calling, you send the model a list of tool definitions — names, descriptions, and JSON Schema parameter shapes — as part of your API request. The model, if it decides a tool is relevant to the user’s request, responds not with plain text but with a structured object naming a function and the arguments to call it with. Your application code is responsible for actually executing that function, then feeding the result back to the model in a follow-up request so it can incorporate the output into its next response.
Crucially, function calling defines nothing about where the tool definitions come from or how they’re maintained. Every application that wants to expose a “search the web” or “query this database” function has to define that tool’s schema itself, in its own code, for every model provider it targets — there’s no shared registry, no standard transport, and no portability of tool definitions between applications.
MCP: a protocol for tool servers
MCP standardizes the other half of the problem: how an AI application discovers and connects to a server that exposes tools, resources, and reusable prompt templates, using a consistent protocol regardless of which model client is consuming it. An MCP server for, say, a company’s internal ticketing system can be written once and then used by any MCP-compliant client — a coding assistant, a chat application, an autonomous AI agent — without each of those clients needing custom integration code for that specific system.
Under the hood, when an MCP client connects to a server, it typically translates the server’s exposed tools into the function-calling schema the underlying model expects. The model still does exactly what it always did with function calling — it emits a structured request to invoke a named function with specific arguments. What MCP adds is the layer above that: a standard way to discover what tools are available, fetch their schemas, and route the actual execution to the right server, instead of every application hardcoding its own tool definitions and dispatch logic.
Where they actually differ
| Function calling | MCP | |
|---|---|---|
| What it is | A model API capability | A client-server protocol |
| Scope | One request’s tool list | A whole server’s tools, resources, and prompts |
| Where it’s implemented | Inside the model provider’s API | Between a client and one or more independent servers |
| Reusability across apps | None — schemas are redefined per app | High — one server, many compliant clients |
| Model-agnostic? | No — tied to a specific provider’s calling format | Yes — the protocol layer is independent of the model |
| Typical unit of work | A single function invocation | Ongoing session: discovery, resources, multiple tool calls |
Function calling answers “how does the model tell my code what it wants to run.” MCP answers “how does my application find, connect to, and standardize access across many different tool providers, without writing bespoke integration code for each one.”
A concrete example
Say you’re building an agent that needs access to a company wiki, a code search index, and a customer database. Without MCP, you’d write three separate integrations, each defining its own function-calling schema, request logic, and response formatting — and if you switched model providers, you might need to adapt each schema to that provider’s specific function-calling format.
With MCP, each of those three systems can instead be exposed as an MCP server — potentially built by the wiki vendor, the code search vendor, and your own internal team, independently. Your agent, built with any MCP-compatible client, connects to all three servers, and the protocol handles discovery (what tools does each server expose?) and invocation in a consistent way. The underlying model still only ever sees function-calling-style tool definitions and returns function-calling-style responses — MCP is what assembled and standardized those definitions before they reached the model.
Why both layers matter
It’s tempting to think MCP “replaces” function calling, but that’s not quite right — MCP is largely built on the premise that function calling works and is reasonably standardized across providers already. What MCP fixes is the fragmentation above that layer: the N×M problem where N applications each need custom integrations with M tool providers. Function calling alone doesn’t address that; it just gives the model a way to ask for a tool call once your application has already decided what tools to offer it.
This mirrors a pattern seen elsewhere in software: a low-level capability (function calling, analogous to a system call) gets a higher-level, portable protocol (MCP, analogous to a shared API standard) built on top of it once enough independent parties need to interoperate through it. Building small MCP servers or clients yourself is a good way to see this in practice — see building your own AI agent for a hands-on starting point.
The takeaway
Function calling is the mechanism by which a model requests a specific tool invocation within a single API exchange — a capability defined by the model provider. MCP is a protocol layered above that mechanism, standardizing how applications discover and connect to tool, resource, and prompt servers so integrations can be written once and reused across clients and models. You don’t choose one over the other in most modern agent stacks — MCP typically depends on function calling working correctly underneath it, and adds the discovery and portability layer that raw function calling never defined.
Tagged
Keep reading
Chisato · · 4 min read What Is Context Engineering? Beyond Prompt Design
Context engineering is the discipline of deciding what an LLM sees at inference time — retrieved documents, tool outputs, memory, and history.
Chisato · · 5 min read Grouped-Query Attention (GQA) Explained: MHA vs MQA vs GQA
Grouped-query attention shares key and value heads across groups of query heads, shrinking the KV cache with little quality loss. GQA vs MHA and MQA.
Chisato · · 5 min read Constrained Decoding: How LLMs Output Guaranteed JSON
Constrained decoding masks invalid tokens at each step so an LLM can only emit output matching a grammar, regex, or JSON Schema. How it works and its limits.