MCP vs Function Calling: How They Relate

Function calling is how a model asks for a tool to be run. MCP is how an application finds tools and reaches the servers that run them. They are two layers of the same loop, and most assistants use both.

7 min read

Function calling and MCP are not rivals; they sit at different layers. Function calling, which Anthropic calls tool use, is a feature of a model’s API: your application sends tool definitions with the request, the model answers with a structured request to call one, and your code runs it. MCP is a protocol between your application and a tool server: how the application discovers which tools exist, how it calls them and how they are served. In a typical assistant, the MCP client fetches tools from each server, hands them to the model as function definitions, and routes whatever the model asks for back to the right server. MCP feeds function calling; it does not replace it. For the protocol itself, see what MCP is.

Function calling, in one round trip

Anthropic’s tool use documentation (opens in a new tab) describes the loop. You pass a tools array, each tool with a name, a description and an input_schema. When the model decides a tool would help, the response stops with stop_reason: "tool_use" and carries a tool_use block naming the tool and its arguments. Your code runs the operation and sends the output back in a tool_result block, and the model carries on.

A tool definition in a Claude API request
{
  "name": "list_tasks",
  "description": "List tasks on a board. Filter by lane or free text.",
  "input_schema": {
    "type": "object",
    "properties": {
      "board": { "type": "string" },
      "lane": { "type": "string", "enum": ["backlog", "next", "doing", "done"] }
    },
    "required": ["board"]
  }
}

OpenAI’s function calling guide (opens in a new tab) lays out the same five steps: define the tools, the model returns a call, your application executes it, you send the result back, and the model answers or calls again. The field names differ between providers; the shape of the loop does not.

Notice what function calling leaves to you. The model never runs anything. Where the tool definitions come from, what code runs when one is called, and which credentials that code uses are all your application’s business.

What MCP adds

MCP standardises exactly the part function calling leaves open. A server publishes its tools; a client asks for them with tools/list and runs one with tools/call. The definition a server returns is almost the same object you would have written by hand, with inputSchema where Claude’s API says input_schema, which is why a client can pass it straight through to the model.

The same tool, as an MCP server lists it
{
  "name": "list_tasks",
  "description": "List tasks on a board. Filter by lane or free text.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "board": { "type": "string" },
      "lane": { "type": "string", "enum": ["backlog", "next", "doing", "done"] }
    },
    "required": ["board"]
  }
}
  • Discovery: the tool list comes from the server at run time, not from code you ship.
  • Reuse: one server works in every client that speaks MCP, instead of one integration per assistant.
  • A standard way to run it: over stdio for a server on the same machine, or over HTTP for a remote one, with the same messages either way.
  • Sign-in for remote servers, built on OAuth, so the server knows whose permissions it is acting under.

What MCP deliberately leaves out is the model. The MCP architecture overview (opens in a new tab) says the protocol focuses solely on exchanging context and does not dictate how AI applications use language models. Deciding which tool to call is still function calling’s job.

How the two fit together in one assistant

  1. The host (Claude Code, Cursor, a chat app) starts one MCP client per configured server.
  2. Each client calls tools/list. The host merges the lists, often prefixing names so two servers’ search tools cannot collide.
  3. The host sends the merged list to the model as function definitions, alongside the conversation.
  4. The model returns a function call: fenbs_list_items with { "board": "kitchen-refit", "lane": "doing" }.
  5. The host finds which server owns that tool and sends tools/call to it.
  6. The server runs the job against its own data and permissions and returns a result.
  7. The host hands the result back to the model as the function call’s output, and the loop continues.

Steps 3, 4 and 7 are function calling. Steps 1, 2, 5 and 6 are MCP. Remove MCP and you write steps 2, 5 and 6 yourself for every tool. Remove function calling and the model has no way to ask for anything.

Where the model APIs meet MCP directly

Some model APIs will now act as the MCP client for you. Claude’s MCP connector (opens in a new tab) lets a Messages API request name remote MCP servers and have Claude call their tools without you running a client. Its documentation lists two limits: only tool calls are supported from the MCP feature set, and the server must be reachable over HTTP, so a local stdio server cannot be connected this way. OpenAI’s function calling guide likewise lists MCP servers among its built-in tool types.

Even here, the layers are the same. The provider runs the MCP client on its side; the model still decides what to call through its tool use mechanism.

The schema is the shared part

Both layers lean on the same thing: a JSON Schema for each tool’s input. That is what makes the hand-off from an MCP server to a model almost free, and it is also where most quality problems start. A schema that accepts any string where it should offer an enum of four lanes invites the model to guess. Anthropic and OpenAI both offer a stricter mode: Claude’s strict tool use (opens in a new tab) makes calls match your schema exactly, and OpenAI recommends its strict mode for function calls.

If you run an MCP server, the schema you publish ends up in every client’s function definitions, so tighten it at the source: enums for fixed values, required for what the job cannot do without, and a one-line description on any field whose meaning is not obvious from its name.

Which one you actually need

  • Plain function calling: your own application, a handful of functions private to it, one model provider. Define the tools inline and run them in your own code. Adding a protocol here buys you little.
  • An MCP server: you want your product usable from Claude, ChatGPT, Cursor, Copilot and whatever comes next, without writing an integration for each. Build the server once.
  • An MCP client with function calling: you are building an agent that should use other people’s tools. Connect to their MCP servers and pass what they list to your model.

Differences that show up in practice

  • Where the code runs: with function calling, in your application. With MCP, in the server, which may belong to someone else and run somewhere else.
  • Who owns the schema: with function calling, you do, and it changes when you deploy. With MCP, the server does, and it can change without your client redeploying.
  • Credentials: with function calling, your code uses whatever credentials your application holds. A remote MCP server receives a token issued to the person who signed the assistant in, and applies that person’s permissions.
  • Errors: both let a tool report failure as a result the model reads. Claude’s tool results take is_error; MCP tool results take isError. Write the message for the model either way: what went wrong and what to try instead.

On a fenbs board, the difference is visible in the history. When Claude Code calls fenbs_update_item, the call came out of Claude’s tool use, travelled to https://fenbs.ai/api/mcp over MCP, and was checked against the role of the person who connected it. The change is recorded as “Claude via” that person, so it can always be told apart from what they did themselves.

Related

Where MCP sits next to a REST API: MCP vs REST API. Writing a server of your own: how to build an MCP server. Connecting an assistant to fenbs: MCP docs, Claude Code, ChatGPT.

Questions people ask.

Is MCP just function calling with extra steps?

No. Function calling is how a model asks for a tool to be run. MCP is how an application discovers tools and reaches the servers that run them. An assistant using MCP still uses function calling to let the model choose a tool.

Does MCP work with models other than Claude?

Yes. MCP is a protocol between an application and tool servers, not a feature of one model. Any application whose model supports function calling can act as an MCP client and pass the tools it discovers to that model.

Do I need MCP if I only use one model provider?

Not for your own private functions; plain function calling is simpler. You want MCP when the tools belong to other products, or when you want your own product usable from assistants you do not control.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.