HelloAI
L4 Chapter 13 🐣 🕒 12 min

Function Calling vs Tool Use vs MCP: How to Tell Them Apart

Three industry terms that keep getting confused — but they're three layers of the same thing. One piece to sort it out.

A
Alai
9/18/2026

Every time someone asks “I want to build an Agent — do I use Function Calling, MCP, or Tool Use?” — it shows no one has explained the three clearly.

This piece does that: they are three layers of the same thing.

One-line distinctions

TermWhat it isDefined byWhich layer
Function CallingOpenAI’s API parameter formatOpenAI (2023)Model API
Tool UseAnthropic’s equivalent featureAnthropic (2023)Model API
MCPCross-vendor tool-invocation protocolAnthropic (2024)App / system

All three solve “let an LLM invoke external tools” — but at different layers.

View 1: API layer (FC / Tool Use)

Have the LLM invoke functions directly through the API:

OpenAI Function Calling

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"]
        }
    }
}]

response = openai.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools
)

Model returns:

{
  "tool_calls": [{
    "function": {
      "name": "get_weather",
      "arguments": "{\"city\": \"Tokyo\"}"
    }
  }]
}

Your code then executes get_weather("Tokyo") and feeds the result back.

Anthropic Tool Use

tools = [{
    "name": "get_weather",
    "description": "Get current weather",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
    }
}]

response = anthropic.messages.create(
    model="claude-3-5-sonnet",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools
)

Nearly identical concept, with slight parameter naming differences.

What they share

  • Both declare tools in the API request body
  • Model returns “I want to call function X with args Y”
  • Your code does the actual execution
  • The model never touches functions directly

The single pain point

Each LLM vendor has its own format. Switching between OpenAI ↔ Anthropic ↔ Gemini ↔ DeepSeek means rewriting tool declarations.

View 2: Protocol layer (MCP)

MCP (Model Context Protocol) answers that pain point:

Why does every tool have to be re-implemented for every LLM?

MCP is a protocol that lets tools “write once, run on every LLM.”

MCP’s role

Before:
  Cursor wants GitHub tools → Cursor implements GitHub integration
  Claude Desktop wants GitHub tools → Claude Desktop implements it again
  Cline wants GitHub tools → Cline implements it again
  → 3× duplicated work

After MCP:
  Someone writes mcp-server-github
  Cursor / Claude Desktop / Cline / Continue all plug in
  → Implement once, used by N clients

What MCP looks like

Not an API call — inter-process communication:

Your app (e.g. Claude Desktop)
   ↓ JSON-RPC over stdio / HTTP
MCP Server (e.g. github, filesystem, postgres)

Real tool (GitHub API, local files, database)

Each MCP server exposes its tools:

# weather_mcp_server.py
from mcp.server import Server

server = Server("weather")

@server.list_tools()
async def list_tools():
    return [Tool(
        name="get_weather",
        description="Get current weather",
        inputSchema={...}
    )]

@server.call_tool()
async def call_tool(name, args):
    if name == "get_weather":
        return [TextContent(text=fetch_weather(args["city"]))]

Once it’s running, any MCP-compatible client (Claude Desktop / Cursor / Cline / Continue / …) can use it.

How the three relate

┌─────────────────────────────────────────┐
│  App layer: Cursor / Claude Desktop / Cline │
└────────────────┬────────────────────────┘

        ┌────────┴────────┐
        ↓                 ↓
   ┌─────────┐      ┌──────────┐
   │   MCP   │      │ Direct   │
   │(protocol)│     │ tool code│
   └────┬────┘      └────┬─────┘
        │                 │
        ↓                 ↓
    MCP Server      Your app code
        │                 │
        └────────┬────────┘

         ┌──────────────┐
         │  LLM API     │
         │ (Function    │
         │  Calling /   │  ← this layer = OpenAI / Anthropic's format
         │  Tool Use)   │
         └──────────────┘


            Real LLM

Key insight:

  • MCP doesn’t replace Function Calling — it lives at a higher layer.
  • An MCP server internally may still use Function Calling to let the LLM decide “which tool to invoke.”
  • But your app code no longer writes Function Calling JSON directly — it talks to MCP servers.

Decision tree

Q: I want my LLM to use tools. Which path?

├─ One LLM vendor only, few tools (≤5)
│   → Use the vendor's native API (Function Calling / Tool Use)

├─ Multiple LLM vendors
│   → Use LangChain / LlamaIndex abstraction (hides differences)
│   → Or just use MCP

├─ Consumer desktop app, want ecosystem sharing
│   → Use MCP (so other apps can use the tools you built)

└─ Enterprise internal Agent platform
    → MCP (decouples tool evolution from Agent evolution)

3 common misconceptions

❌ “MCP replaces Function Calling”

Correct: MCP is a protocol; Function Calling is an API format. They coexist. MCP servers often still use FC internally.

❌ “Using MCP means you must use Claude”

Correct: MCP is an open protocol. OpenAI / Google / Mistral are all evaluating support. MCP servers are LLM-agnostic.

❌ “Function Calling is for OpenAI, Tool Use is for Claude — pick one”

Correct: If your app supports both vendors, write both schemas. Or use LangChain / DSPy to write it once.

A real industry architecture

A 2026 production Agent (e.g. Cursor):

[User: "fix the bug in main.py"]

[Cursor app]
        ↓ ① List of MCP-connected tool servers
        │   - mcp-server-filesystem (file I/O)
        │   - mcp-server-git (git ops)
        │   - mcp-server-shell (run commands)
        ↓ ② Collect all tool schemas
[LLM API call]
        ↓ ③ Use Anthropic Tool Use format (Cursor talks to Claude)
        │   tools=[{"name": "...", ...}, ...]
[LLM decides which tool to use]
        ↓ ④ Returns a tool_use call
[Cursor routes it to the right MCP server]

[MCP server executes]

[Result flows back to LLM]

[LLM decides the next step]

MCP is on the outside (managing the tool ecosystem); Function Calling / Tool Use is on the inside (talking to the LLM).

💡 Summary

Function Calling / Tool Use is one LLM vendor’s format for declaring tools — it solves “how does the LLM tell me which function to call?”

MCP is a protocol — it solves “how is this tool reused across multiple LLM clients?”

They are complementary, not mutually exclusive. In real systems they appear together.

Next: L4-14 Structured output or L4-11 Writing your own MCP server.

🚧 3 Common Pitfalls

⚠️ Real-world traps

Pitfall 1: Treating the three terms as synonyms FC is an interface, Tool Use is a paradigm, MCP is a protocol — mixing them in discussions causes team misalignment.

Pitfall 2: Thinking MCP = OpenAI Plugins 2.0 MCP is a protocol (any client + any server); Plugins was ChatGPT-internal architecture. MCP is far more general.

Pitfall 3: Not distinguishing single-step vs multi-step A single function call isn’t Tool Use; multi-turn tools + reflection + deciding the next step is.