Function calling defines a tool inside one app's API request and your code runs it. MCP puts the same tool on a server that any MCP client can discover and call. They are not rivals: the model makes the same kind of tool call either way. Use function calling for tools one product owns, MCP for tools several clients share, and both once you have each kind.
Function calling vs MCP comes down to where the tool lives: function calling defines a tool inside one app's API request and your own code runs it, while MCP puts the tool on a server that any MCP client can discover and call. The model does the same thing in both cases, which is to return a tool name and JSON arguments, so the choice is about ownership and reuse, not capability.
Checked October 2026 against Anthropic's tool use, MCP connector and tool search docs, OpenAI's function calling and MCP servers guides, Google's Gemini function calling page, and the MCP specification (tools, authorization, 2026-07-28 changelog).
This comparison is built from those documents, not from our own benchmarks: every token figure below is a number Anthropic or OpenAI publishes, and the cost lines are labelled arithmetic. For what input tokens cost per model, keep our LLM API pricing comparison open in another tab. If MCP itself is new to you, read what the Model Context Protocol is first.
Function calling vs MCP: the short answer
Use function calling when one app owns the tool. Use MCP when more than one client needs it. Use both when your product has private logic and shared systems, which describes most products once they are past the prototype.
- Pick function calling if the tool touches your own database or internal state, only your app will ever call it, and you want nothing extra to host or secure.
- Pick MCP if the same tool should work in a coding assistant, an agent platform and your own app, or if a vendor already ships an official server for the system you need.
- Pick both if you have a few private functions and want to plug in shared servers next to them. The APIs accept the two kinds in one request.
A note on names before the detail. "Tool use", "tool calling" and "function calling" are the same feature: Anthropic's docs introduce tool use as "also called function calling", and OpenAI describes a function as one kind of tool. This page uses function calling for tools you define in the request.
MCP vs function calling, side by side
| Function calling | MCP | |
|---|---|---|
| What it is | A feature of one model API | An open protocol between AI apps and tool servers |
| Where the tool is defined | In the tools array of your API request | On a server; clients discover it with tools/list |
| Who runs the code | Your application, in its own process | The MCP server, a separate process or web service |
| Who can use it | The app that defines it | Any MCP client: coding assistants, desktop AI apps, agent platforms and the model APIs |
| Auth | Nothing new. Your app already holds the credentials | Optional OAuth 2.1 for remote servers; environment credentials for local stdio |
| Token cost | Each definition is billed as input tokens on every request | The same per tool, times every tool the server exposes unless you filter |
| To change a tool | Redeploy your app | Redeploy the server; every client picks up the change |
| Approval | Whatever your code enforces | The spec says a human should be able to deny calls; hosts and APIs add approval settings |
| Fits | Tools private to one product | Tools shared across products, agents or customers |
The row people skip is the one that settles most arguments: from the model's side, the two are identical. An MCP client fetches tool definitions from a server and hands them to the model as ordinary tools. What comes back is an ordinary tool call.
- 01The model receives tool definitions
Function calling: from the tools array in your request. MCP: fetched from the server with tools/list, then passed to the model.
- 02The model returns a tool call
A tool name and JSON arguments. The same shape on both routes.
- 03Something runs it
Function calling: your code. MCP: the client sends tools/call and the server executes it.
- 04The result goes back
As a tool result in the conversation, which the model reads on the next turn.
- 05The model answers or calls again
The loop repeats until it has what it needs.
So MCP is not a smarter way for a model to use tools. It is a standard way to package them, so the integration is written once per system instead of once per app.
The same CRM tool, three ways
Take one read-only tool: look up a contact in a CRM by email address. The names and URLs below are illustrative, and the request shapes follow the vendors' documented examples.
1. As a function
This is the definition in Anthropic's shape. OpenAI's differs only in the envelope: a type of function, parameters instead of input_schema, and a strict flag that OpenAI recommends turning on.
{
"name": "lookup_contact",
"description": "Look up one CRM contact by email address. Returns the contact's name, company, account owner and deal stage. Use it when the user asks about a specific person or account. It does not search by name and it never changes data.",
"input_schema": {
"type": "object",
"properties": {
"email": {
"type": "string",
"description": "The contact's email address, e.g. dana@example.com"
}
},
"required": ["email"]
}
}Your app sends this in the tools array of every request. When the model answers with a tool call for lookup_contact, your code queries the CRM with a key the model never sees and returns the row. The long description is deliberate: Anthropic calls detailed descriptions the most important factor in tool performance and suggests at least three or four sentences per tool.
2. As an MCP tool
Move the handler behind an MCP server and this is the entry a client receives from tools/list:
{
"name": "lookup_contact",
"title": "Look up a CRM contact",
"description": "Look up one CRM contact by email address. Returns the contact's name, company, account owner and deal stage. Use it when the user asks about a specific person or account. It does not search by name and it never changes data.",
"inputSchema": {
"type": "object",
"properties": {
"email": {
"type": "string",
"description": "The contact's email address, e.g. dana@example.com"
}
},
"required": ["email"]
}
}Same name, same description, same JSON Schema under a different key. What changed is the owner. The server now holds the CRM credentials and runs the query, and any client that connects can call the tool without a line of integration code.
3. As both
You do not need to write an MCP client to use that server from your own backend. Anthropic's MCP connector, in beta, attaches a remote server from the Messages API request. The server goes in mcp_servers and must be referenced by an mcp_toolset entry in tools:
curl https://api.anthropic.com/v1/messages \
-H "Content-Type: application/json" \
-H "X-API-Key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: mcp-client-2025-11-20" \
-d '{
"model": "claude-opus-5-5",
"max_tokens": 1000,
"messages": [{"role": "user", "content": "Who owns the account for dana@example.com?"}],
"mcp_servers": [
{
"type": "url",
"url": "https://crm.example.com/mcp",
"name": "crm",
"authorization_token": "YOUR_TOKEN"
}
],
"tools": [
{ "type": "mcp_toolset", "mcp_server_name": "crm" }
]
}'Your private functions can sit in the same tools array next to the toolset. Two limits from the connector docs: it supports tool calls only, not the rest of the MCP feature set, and the server must be reachable over public HTTPS, so a local stdio server cannot be attached this way.
| As a function | As an MCP server | As both | |
|---|---|---|---|
| Code you write | A definition and a handler in your app | The same handler behind an MCP server | One handler; the server attached from your API call |
| Hosting | None beyond your app | A public HTTPS endpoint for remote use, or a local process | The server, plus your app |
| Auth | Your app's existing CRM key | An OAuth access token per client for remote; environment variables for local | A token for the server, passed as a field in the request |
| Reuse | This app only | Every MCP client you allow in | Every MCP client, and your own API calls |
| Tokens per request | One definition | One if you allowlist it; every tool on the server if you do not | Whatever you load. Never load the same tool twice |
Token overhead: where the real difference shows up
One tool costs the same either way: its definition is input tokens on every request. OpenAI says so directly (function definitions "count against the model's context limit and are billed as input tokens"), and the same applies once an MCP tool has been loaded. The gap opens because a server hands you its whole catalogue.
- Anthropic's example: GitHub, Slack, Sentry, Grafana and Splunk servers together
- Tool search typically cuts this by over 85 percent
- Tool selection gets worse past 30 to 50 available tools
Source: Anthropic tool search tool documentation, checked October 2026
Put a price on that with arithmetic from published rates. Claude Opus 5.5 lists $4 per million input tokens (checked October 2026), so 55,000 tokens of definitions is $0.22 on every uncached request, before the user's question is read. At 1,000 requests a day that is $220 a day for tool descriptions. The same block read from the prompt cache, at $0.20 per million, is about one cent.
Both vendors document the fixes, and they apply to functions and MCP tools alike:
| Lever | What it reduces | When it fits |
|---|---|---|
| Allowlist tools | Tools imported from a server | You need three tools from a server that exposes forty |
| Tool search | Tool definitions loaded up front | Large toolsets (20+ tools) where most are not needed every turn |
| Prompt caching | The price of repeated definitions | A stable toolset sent on many requests |
| Context editing | Old tool results kept in history | Long conversations where early results no longer matter |
The allowlist is the cheapest. All three APIs take one when you attach a server, and OpenAI's guide gives the reason: servers "can have dozens of tools", and exposing many of them raises cost and latency. OpenAI also suggests keeping fewer than 20 functions available at the start of a turn, as a soft target. One detail from the MCP spec helps caching: servers should return tools in a deterministic order, precisely so clients can cache the list and prompt caches keep hitting.
Auth and trust: the part that gets skipped
Function calling adds no auth surface. Your app runs the function with credentials it already has, and the model only ever sees arguments and results. If the function is dangerous, the guard is your own code.
A remote MCP server is a network service of its own, so somebody has to authenticate to it. The specification makes authorization optional and, for HTTP servers, bases it on OAuth 2.1: the server is a resource server and the client presents an access token on each request. A server may return a different tool list depending on the scopes in that token. Local stdio servers skip all this and read credentials from the environment. When you attach a server from a model API, you obtain the token yourself and pass it in a request field.
Tool calling vs MCP: what is different now
Most confusion comes from advice written when MCP was a desktop-app feature. Five assumptions from that period no longer hold.
- MCP only works inside desktop apps and IDEs
- An MCP connection is a stateful session that starts with a handshake
- Every connected tool loads into context on every request
- Function calling and MCP are competing standards
- Remote servers are built on SSE
- Anthropic, OpenAI and Gemini APIs each attach a remote MCP server from the request
- The 2026-07-28 spec is stateless: no initialize handshake, no session header
- Tool search defers definitions until the model asks for them
- An MCP tool reaches the model as an ordinary tool call
- Streamable HTTP is the transport; HTTP+SSE is deprecated
The first row is the practical one. You can keep your own agent loop, written with plain function calling, and add an MCP server as one more entry in the request:
| API | How you attach a remote MCP server | Transport | Token field | Filtering |
|---|---|---|---|---|
| Anthropic Messages API | An mcp_servers entry plus an mcp_toolset in tools; beta header mcp-client-2025-11-20 | Public HTTPS, Streamable HTTP or SSE. No local stdio | authorization_token | Allowlist or denylist tools |
| OpenAI Responses API | A tool with type mcp and server_url, or tunnel_id through Secure MCP Tunnel for private servers | A remote server on the public internet, or the tunnel | authorization | allowed_tools; require_approval |
| Gemini Interactions API | A tool with type mcp_server, a name and a url | Streamable HTTP only. SSE servers are not supported | headers | allowed_tools |
The stateless change matters if you host a server. In the 2026-07-28 revision each request carries its protocol version and client capabilities, and tool lists no longer vary per connection, which makes a server much easier to run behind an ordinary load balancer. OpenAI adds a billing note worth knowing: with its MCP tool you pay only for the tokens used when importing tool definitions or making tool calls, with no extra fee per call.
When to use function calling, MCP or both
Start with a function and extract it when a second consumer shows up. That order costs you nothing, because the definition carries over unchanged.
- 1Write the tool as a function in your app
A clear name, a description of three or four sentences and a JSON Schema for the arguments.
- 2Keep the logic in one plain handler
Validated arguments in, a small JSON result out. No SDK types inside it, so it can be reused.
- 3Watch for the second consumer
A teammate wants it in a coding assistant, another service needs it, or a customer asks to use it from their own AI client.
- 4Wrap the same handler in an MCP server
Keep the name, description and schema identical so prompts that mention the tool still work.
- 5Put auth on the server
OAuth for remote access, the narrowest scopes that do the job, read-only tools first.
- 6Attach it from your API calls
Use the provider's MCP field with an allowlist, and remove the duplicate function definition.
If you only consume tools, the decision is simpler: where a vendor ships an official MCP server, use it rather than wrapping the vendor's API in your own functions. Our lists of the most useful MCP servers and the best MCP servers for coding cover which ones hold up.
And if the steps never change, you may need neither. A nightly sync or a webhook handler should call the API directly from code; tools are for cases where the model decides what to do next. For the code side of each route, our Claude API function calling tutorial walks through the tool loop in TypeScript, and the AI SaaS Builder program has lessons on both halves: tool use and structured output on the Claude API, then building your first MCP server and putting MCP into a product.
Function calling vs MCP: FAQ
What is the difference between function calling and MCP?
Function calling is a feature of a model API: you describe a tool with a name, a description and a JSON Schema in your request, the model returns a structured call, and your code runs it. MCP, the Model Context Protocol, is an open protocol that puts tools on a server so any compatible client can discover them with tools/list and invoke them with tools/call. Function calling is how a model asks for a tool; MCP is how tools are packaged and shared.
Does MCP replace function calling?
No. An MCP tool still reaches the model as a tool definition and comes back as a tool call, the same mechanism function calling uses. MCP changes who hosts the tool and who can reuse it. A product with a handful of private tools loses nothing by staying on function calling, and many production apps use both: in-process functions for their own logic, MCP servers for shared or third-party systems.
Is tool calling the same as function calling?
In practice, yes. Anthropic's documentation calls the feature tool use and notes it is also called function calling. OpenAI's guide treats a function as one kind of tool, defined by a JSON schema, next to built-in tools such as web search and the MCP tool. When people say tool calling they usually mean the model emitting a structured request for any tool, whether it is your function or a hosted one.
Does MCP use more tokens than function calling?
Per tool, no: a definition costs input tokens either way. The difference is volume. Connecting a server loads every tool it exposes unless you filter, and Anthropic's documentation puts a typical five-server setup at about 55,000 tokens of definitions before any work starts. Allowlisting tools, prompt caching and tool search, which defers definitions until the model asks for them, bring that down. Checked October 2026.
Can I use an MCP server directly from the OpenAI, Claude or Gemini API?
Yes, for remote servers, checked October 2026. Anthropic's Messages API has an MCP connector in beta that uses mcp_servers plus an mcp_toolset entry. OpenAI's Responses API has an mcp tool type with server_url. Gemini's Interactions API has an mcp_server tool type, limited to Streamable HTTP servers. All three let you restrict which tools load. Local stdio servers need a client app or a tunnel instead.
How does authentication differ between function calling and MCP?
With function calling there is no new auth surface: your app runs the function with credentials it already holds, and the model only sees arguments and results. A remote MCP server is its own network service, so the specification defines an optional OAuth 2.1 flow in which the client presents an access token on each request. Local stdio servers read credentials from the environment. The model APIs accept that token as a request field.
When should I build an MCP server instead of writing functions?
Build one when a second consumer appears: another app, a coding assistant, an agent platform or a customer's own AI client needs the same tools. Until then a function inside your app is less to host, secure and monitor. A workable path is to write the tool as a plain function first and wrap that same function in an MCP server later, keeping the name, description and schema identical.
Know which one you need? Now build the tool.
AI SaaS Builder, included in All Access, covers tool use on the Claude API and building and shipping your own MCP server, with Supabase, deployment and billing around them, alongside the other three programs, live coaching and the private community.
Stuck choosing between a function and a server?
Describe the tool in the free Discord and get a second opinion from other people building agents and AI products.