MCP vs Function Calling: What's the Difference?
Short answer: they're not competitors. Function calling is how a model asks for a tool to be run. MCP is how applications discover and connect to tools. Function calling is the verb; MCP is the plumbing. Here's the full picture.
What function calling is
Function calling (also called "tool use") is a model capability. When you
call an LLM API, you pass a list of function definitions — names, descriptions, JSON
schemas. The model can respond with "call get_weather with
{"city": "Berlin"}" instead of plain text. Then your code executes
the function and feeds the result back.
// Function calling with an LLM API (simplified)
const response = await client.messages.create({
model: "claude-sonnet-4-5",
tools: [{
name: "get_weather",
description: "Get current weather for a city",
input_schema: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"]
}
}],
messages: [{ role: "user", content: "Weather in Berlin?" }]
});
// → response contains a tool_use block; YOU run the function.
This works great — but notice what's missing: there's no standard for where the functions come from. Every app hard-codes its own tool list and its own execution logic.
What MCP adds
MCP is an integration protocol. Instead of hard-coding tools into one app, you package them in an MCP server. Any MCP-compatible application can then:
- Discover the tools at runtime (
tools/list) — no redeploy needed when tools change. - Call them through a standard interface (
tools/call). - Combine tools from many servers in one session.
Under the hood, MCP clients still use function calling — they take the tool list from your MCP servers and hand it to the model as function definitions. MCP doesn't replace function calling; it standardizes everything around it.
Side by side
| Function calling | MCP | |
|---|---|---|
| What it is | A model/API capability | An open integration protocol |
| Who defines tools | Your application code, per app | An MCP server, reusable everywhere |
| Tool discovery | Hard-coded at build time | Dynamic, at runtime |
| Who executes | Your app, custom logic | The MCP server, behind a standard interface |
| Reuse | One app | Every MCP client (Claude, VS Code, Cursor, ChatGPT…) |
| Beyond tools | Tools only | Tools + resources + prompts |
When to use which
Use plain function calling when…
- You're building one application with a fixed, small set of tools.
- The tools are tightly coupled to your app's internals and will never be shared.
- You want minimal moving parts — no server processes, no protocol layer.
Use MCP when…
- You want your tools available in apps you don't control — Claude Desktop, VS Code, Cursor, ChatGPT.
- Multiple teams or projects need the same integrations (one Postgres server, used everywhere).
- You're building a devtool or SaaS product and want AI assistants to operate it. An MCP server is your AI-facing API.
- Your agent should compose tools from many sources at runtime.
Rule of thumb: hard-coding three functions into one chatbot? Function calling is enough. Building tools that should outlive any single app? MCP.
They work together
This is the key insight people miss: in every MCP-powered app, both layers are active. The MCP client gathers tools from connected servers → presents them to the model as function definitions → the model uses ordinary function calling to pick one → the client routes the call to the right MCP server. Learning MCP doesn't mean unlearning function calling — it means you stop rebuilding the integration layer for every project.
Get the MCP curriculum by email
New tutorials and guides as they're published, in order — from fundamentals to production. Free.
First lesson is on its way.
No spam. Unsubscribe anytime.