Guide
LLM function calling vs MCP: how they relate and when each applies
Function calling and MCP are not competing options. Function calling is how a model asks for a tool to be used. MCP is a protocol for how an application discovers and calls tools that live in a separate server. Use plain function calling for tools inside your own app, and add MCP when tools need to be shared or are already available as servers.
Two different conversations
The confusion comes from both being described as "giving a model tools". They in fact govern two separate conversations, and a single tool use can involve both.
- Function calling is between your application and the model provider. You send tool definitions with a request, and the model may reply with a structured request to call one. The format is set by each provider's API.
- MCP is between an MCP client and an MCP server. The client asks which tools exist with
tools/listand runs one withtools/call, using JSON-RPC messages. The format is set by the protocol's specification, whichever model is in use.
So the two meet at your application, or at a provider acting on its behalf. This guide assumes you know the basics of each. If not, begin with tool calling for AI agents, which covers designing and validating tools, and Model Context Protocol for AI agents, which covers the protocol's participants and primitives. Here the question is only how the two relate.
One tool use, step by step
Suppose a user asks an assistant to look up a support ticket, and the search tool lives in an MCP server. In the classic arrangement the steps are:
- MCP: the application's client sends
tools/listand receives the tool's name, description and input schema. - Translation: the application rewrites that definition into its model provider's tool format.
- Function calling: the application sends the conversation and the tools to the model, which returns a structured call with arguments.
- Your code: the application checks the call against its own rules.
- MCP: the client sends
tools/callto the server and receives a result. - Function calling: the application passes the result back to the model in the provider's format, and the model continues.
The model never has to know about MCP. It sees a tool definition, just as it would for a local function. In the same way, the MCP server does not need to know which model is being used.
What each one leaves out
| Question | Function calling | MCP |
|---|---|---|
| Who defines the format? | Each model provider | The MCP specification |
| Decides that a tool is needed? | The model | Out of scope; the host handles the model |
| Finds out which tools exist? | You supply them on each request | tools/list, which can be paged |
| Where does the tool run? | Usually your application | In a separate server, local or remote |
| Offers more than tools? | Depends on the provider's API | Also defines resources and prompts |
Function calling on its own gives no standard way to share a tool with another application. MCP on its own does not make a model pick a tool. Each covers the gap in the other, which is why they so often appear together.
Three ways to wire them up
1. Plain function calling
Tool definitions and code live in your application. As OpenAI's function calling guide describes, the model returns a call and your application runs it and sends the output back. Anthropic's tool use documentation calls these client tools and follows the same round trip. There is no extra process to deploy, and every call passes directly through your code.
2. Your application as an MCP client
Your application connects to MCP servers and handles the translation in steps 1 to 6 above. This is the only one of the three options that can reach a local stdio server, since the client launches that server as a subprocess. It also keeps a checkpoint in your code before every tools/call.
The translation itself is usually short. Field names differ by provider; this example targets Anthropic's documented input_schema field:
# Illustrative only. Converts one MCP tool definition for a provider
# whose tool format uses name, description and input_schema.
def to_provider_tool(server_name, mcp_tool):
return {
"name": f"{server_name}__{mcp_tool['name']}",
"description": mcp_tool.get("description", ""),
"input_schema": mcp_tool["inputSchema"],
}
def split_tool_name(provider_name):
server_name, tool_name = provider_name.split("__", 1)
return server_name, tool_name
This sample is illustrative, and it assumes server names contain no double underscore. The prefix matters because tool names are unique only within a single server. The specification notes that two servers may each expose a search tool and that clients should disambiguate them, for instance with a server prefix. Check your provider's limits on tool name length and characters as well, since a prefix makes names longer.
Errors need mapping too. The specification separates protocol errors, such as an unknown tool, from tool execution errors, reported in a result with isError: true. It says clients should pass execution errors to the model so that it can correct itself, whereas protocol errors are less likely to help. An adapter that treats both alike loses that distinction.
3. The provider connects to the server
Some APIs can call a remote MCP server for you. You name the server in the request, and the provider handles listing and calling, so your application writes no client code. OpenAI documents a remote MCP tool in its Responses API, and Anthropic documents an MCP connector for its Messages API, marked as beta when this was written.
The convenience comes with constraints. Anthropic's connector supports only tool calls from the MCP feature set, requires a server publicly exposed over HTTP and cannot reach local stdio servers directly. A call also runs without passing through your code first, so your checks have to use whatever the provider offers. OpenAI's tool, for example, requests approval by default and can limit which tools are imported. Its documentation warns that a malicious server could exfiltrate sensitive data from anything in the model's context, and advises connecting only to servers you trust. Features vary by provider and change quickly, so read the current documentation before relying on this option.
How to choose
| Your situation | Reasonable starting point |
|---|---|
| A few tools used only by one application | Plain function calling |
| Several applications or teams need the same integration | An MCP server, with each application as a client |
| You want to use an existing MCP server inside your product | Your own client, or a provider connector if it is remote and trusted |
| You want your tools available in existing MCP-compatible assistants | Build an MCP server |
| Tools need local files or processes on the user's machine | Your own client with a stdio server |
| Each call must pass your own policy checks | Function calling or your own client |
| You need to swap model providers easily | Keep tools behind your own client or layer, whichever protocol sits beneath it |
The options can also be mixed. A common shape keeps a handful of application-specific functions in-process, where they can use your session and database directly, while reaching shared capabilities through MCP. The model sees one flat list of tools, and your dispatcher decides where each call goes.
Common misconceptions
- "MCP replaces function calling." In the classic arrangement above, the model still asks for a tool through its provider's mechanism. MCP changes where the tool comes from and how it is reached.
- "MCP makes tools safe." The specification states that servers must validate inputs and apply access controls, and that clients should confirm sensitive operations and validate results. Those duties still have to be carried out by someone.
- "A schema guarantees a sensible call." A valid call can still be the wrong action or target the wrong record. Business rules belong in your code or the server.
- "Adding a server costs nothing." Each definition uses context, and a long list makes selection harder. Importing a server's whole catalogue can quietly degrade tool choice, so expose only what the agent needs.
- "A standard protocol fixes the version." MCP versions its revisions by date, and 2026-07-28 was the current one when this guide was written. That revision moved away from the handshake used in earlier ones, so confirm what your SDKs and servers support.
A sensible path
Start with plain function calling unless you already know the tools must be shared. Keep each tool's logic in an ordinary function behind a thin wrapper, because exposing that same function through an MCP server later is then a small change. Move to MCP when a second consumer appears or a useful server already exists, and treat that decision as being about integration and ownership, not model capability.
If you are planning an LLM feature and working out how it should reach your systems, the generative AI and LLM development page describes what I can help with.
Frequently asked questions
Does MCP replace function calling?
No. They work at different layers. Function calling is how a model requests a tool through a provider's API, while MCP standardises how a client discovers and calls tools on a server. An application often uses both for one tool call.
Can I use MCP without function calling?
Yes, as a protocol. A client can call an MCP tool directly with no model involved, and that is useful for testing. To let a model choose the tool, though, it needs a way of requesting one, which is usually its provider's tool mechanism.
Does MCP work with any LLM?
The server does not depend on a particular model. Your application can translate MCP tool definitions into the tool format of any model that supports tool use. Hosted connectors are different, since each is a feature of a specific provider's API.
Should I build an MCP server for my own app's tools?
Often not at first. If one application uses a few of its own functions, in-process function calling is simpler. A server becomes worthwhile when other applications or teams need the same tools, or when you want them available in MCP-compatible clients.