MCP vs Function Calling: Which Should You Use?
MCP vs function calling: understand the architectural trade-offs, token costs, security models, and when each approach wins in production Claude agent systems.
By Solomon Udoh · AI Architect & Certification Lead

The debate over mcp vs function calling is not academic. It shapes how your agent handles auth, how many tokens it burns per turn, and whether your tool layer survives a production security audit. Both mechanisms let Claude invoke external capabilities, but they operate at different layers of the stack and carry different operational costs. This post maps the distinction precisely, then gives you a decision framework for each scenario you are likely to face.
What is the difference between MCP and function calling?
Function calling is the native Claude API mechanism. You define tools as JSON schemas in the tools array of a Messages API request. Claude reads those definitions, decides which tool to invoke, and returns a tool_use content block. Your application code executes the function and appends the result as a tool_result message. The entire lifecycle lives inside a single conversation turn, managed by your code.
The Model Context Protocol (MCP) is a separate, open protocol that standardises how Claude connects to external servers that expose tools, resources, and prompts. An MCP server is a running process (local or remote) that advertises its capabilities over a defined transport. Claude Code and the Claude API both support MCP natively. The key architectural difference: with function calling, your application owns the tool execution; with MCP, a dedicated server owns it.
Tools in the
toolsparameter are defined directly in the API request and executed by your application. MCP tools are defined by an external server process and executed there, with results returned over the protocol transport.
How does each mechanism actually work?
Function calling: the request-response loop
The Messages API request-response cycle for function calling follows four steps:
- You send a request with a
toolsarray containing JSON schema definitions. - Claude returns
stop_reason: "tool_use"with one or moretool_useblocks. - Your application executes the function and collects the result.
- You append a
tool_resultmessage and send the next request.
A minimal tool definition looks like this:
{"name": "get_order_status","description": "Returns the current status of a customer order by order ID.","input_schema": {"type": "object","properties": {"order_id": {"type": "string","description": "The unique order identifier, e.g. ORD-20260312-001"}},"required": ["order_id"]}}
And the Python call that wraps it:
import anthropicclient = anthropic.Anthropic()response = client.messages.create(model="claude-opus-4-5",max_tokens=1024,tools=[{"name": "get_order_status","description": "Returns the current status of a customer order by order ID.","input_schema": {"type": "object","properties": {"order_id": {"type": "string"}},"required": ["order_id"]}}],messages=[{"role": "user", "content": "What is the status of order ORD-20260312-001?"}])
The stop_reason field inspection and tool result appending patterns are the two mechanics you must handle correctly on every loop iteration.
MCP: the server-mediated model
With MCP, you configure one or more servers in a config file or programmatically. Claude Code uses a ~/.claude/mcp.json file; the API uses the mcp_servers parameter (where supported). The server advertises its tools via the protocol handshake, and Claude selects from them exactly as it would from inline tool definitions. The difference is that execution happens inside the server process, not in your application.
A minimal MCP server config entry:
{"mcpServers": {"order-service": {"command": "node","args": ["/opt/mcp-servers/order-service/index.js"],"env": {"ORDER_API_KEY": "${ORDER_API_KEY}"}}}}
Note the ${ORDER_API_KEY} pattern: environment variable expansion in MCP config keeps secrets out of config files, which matters for audit trails.
How do the two approaches compare on the dimensions that matter?
| Dimension | Function Calling | MCP |
|---|---|---|
| Execution location | Your application code | Dedicated server process |
| Transport | None (in-process) | stdio (local) or HTTP/SSE (remote) |
| Auth model | You implement it | Server-level, can be OAuth-bound |
| Tool discovery | Static (defined per request) | Dynamic (server advertises at runtime) |
| Token cost of definitions | Billed per request | Billed per request (same schema format) |
| Reusability across agents | Manual copy or shared library | Any agent that connects to the server |
| Audit trail | Your logging | Server-side logging, centralised |
| Spec stability | Stable (Messages API) | Evolving (MCP spec is a moving target) |
| Setup complexity | Low | Medium to high |
| Legacy system integration | Direct (your code calls the system) | Requires server wrapping the system |
Both mechanisms use the same JSON schema format for tool definitions, so token costs for the definitions themselves are equivalent. Where MCP can cost more tokens is when you connect many servers simultaneously: each server's full tool catalogue is loaded into context. The tool overload problem is a real production concern; connecting ten MCP servers with twenty tools each puts two hundred tool definitions in every request.
When should you use function calling?
Function calling is the right default when:
- You are building a single-application agent where tool execution is tightly coupled to application logic.
- Your tools are few (fewer than ten), stable, and not shared across multiple agents.
- You need the lowest possible setup overhead for a prototype or internal tool.
- You are integrating a legacy system that you cannot expose as a network service. Your application code calls the legacy API directly and returns the result as a
tool_result. - You need deterministic, auditable execution that lives entirely within your existing application security boundary.
The tool descriptions as selection mechanism principle applies equally here: even with inline function calling, a poorly written description causes misrouting. The mechanism is different; the description quality requirement is identical.
When should you use MCP?
MCP earns its setup cost when:
- You need the same tools available to multiple agents or multiple Claude surfaces (Claude Code, API agents, future integrations).
- You want centralised auth, logging, and rate limiting at the tool layer rather than reimplementing them in every agent.
- You are operating in an enterprise environment where security teams require audit trails at the tool execution layer.
- You want to consume pre-built connectors for systems like Salesforce or SAP rather than writing bespoke integration code.
- Your tools return structured data that benefits from server-side normalisation before Claude sees it.
For production enterprise governance, remote MCP servers with OAuth-bound scoped permissions give security teams a single enforcement point. Every tool call passes through the server, which can log the caller identity, the parameters, and the result. That audit trail is difficult to replicate cleanly with inline function calling spread across multiple application codebases.
The Model Context Protocol enables a standardised way for AI models to connect with external data sources and tools, with the goal of making integrations more composable and reusable.
What are the token efficiency trade-offs?
Token efficiency deserves its own section because it is the most common production complaint about MCP at scale.
With function calling, you control exactly which tools appear in each request. You can send a minimal tool set for simple tasks and a richer set for complex ones. With MCP, the server advertises its full catalogue and Claude receives all of it. If you connect five MCP servers with fifteen tools each, you are paying for seventy-five tool definitions on every request, whether Claude uses them or not.
Mitigation strategies:
- Use the
tool_choiceparameter to constrain which tools Claude may select on a given turn. The tool_choice configuration options let you force a specific tool or restrict to a subset. - Split large MCP servers into smaller, role-scoped servers. Connect only the server relevant to the current task.
- Write tight, short tool descriptions. Every token in a description is billed on every request that includes that tool. The writing effective tool descriptions principle applies with extra urgency at MCP scale.
- For Claude Code workflows, use MCP scoping hierarchy to configure servers at the project level rather than globally, so only relevant servers load for each project.
How does security differ between the two models?
Security is where the architectural difference becomes most consequential for enterprise teams.
With function calling, your application code is the security boundary. You validate inputs before executing, you handle auth to downstream systems, and you decide what to return. This is flexible but means every agent application must implement security correctly and independently.
With MCP, the server is the security boundary. A well-designed MCP server can:
- Enforce OAuth scopes so that different callers get different tool access.
- Validate and sanitise all inputs before touching downstream systems.
- Rate-limit calls per client identity.
- Emit structured audit logs to a SIEM.
- Reject calls that would expose internal service endpoints to external traffic.
For legacy system integration specifically, a local MCP server (stdio transport) can wrap an internal API without exposing it as a network service. The server runs on the same host as the agent, communicates over stdin/stdout, and calls the legacy system over an internal network. This is often the cleanest architecture for integrating systems that cannot be exposed externally.
The trade-off is spec stability. The MCP specification is still evolving, and teams building production MCP servers need to budget for protocol updates. Function calling, by contrast, is a stable Messages API feature with a long track record.
How does this map to the CCAR-F exam?
Tool Design and MCP Integration is Domain 2 of the CCAR-F exam, weighted at 18%. The exam tests practical judgment, not recall, so expect scenario-based items that ask you to choose between inline function calling and MCP given specific constraints: team size, security requirements, token budgets, and reuse patterns.
The exam consistently rewards deterministic solutions over probabilistic ones when stakes are high. In tool design scenarios, that means preferring explicit scoping, structured error responses via the MCP isError flag pattern, and audit-friendly architectures over clever but opaque ones.
Domain 1 (Agentic Architecture and Orchestration, 27%) also touches this topic through hub-and-spoke architecture patterns, where a coordinator agent routes tasks to specialised subagents, each with its own scoped tool set. Whether those tools are inline or MCP-served is an architectural decision the exam may ask you to justify.
Our concept library at /concepts covers 174 atomic concepts mapped to all five CCAR-F domains, including the full Tool Design and MCP Integration domain. The adaptive engine uses Bayesian Knowledge Tracing with a 0.90 mastery threshold, so it will surface MCP vs function calling scenarios until you have genuinely internalised the trade-offs, not just memorised the labels.
What is the practical decision rule?
If you are building one agent for one application and your tools are stable and few: use function calling. It is simpler, cheaper to operate, and easier to debug.
If you are building tools that multiple agents will share, operating in an environment with centralised security requirements, or want to consume a growing ecosystem of pre-built connectors: invest in MCP. The setup cost pays back quickly when the alternative is reimplementing auth and logging in every agent.
The two are not mutually exclusive. A production agent can use inline function calling for application-specific, low-reuse tools while connecting to MCP servers for shared enterprise capabilities. The build vs use decision for MCP servers framework helps you decide which tools warrant a dedicated server and which are better kept inline.
Frequently asked questions
Can I use both MCP and function calling in the same Claude agent?
Does MCP cost more tokens than function calling?
Is MCP supported in the Claude API or only in Claude Code?
How do I handle errors differently in MCP versus function calling?
What is the best way to integrate a legacy system that cannot be exposed as a network service?
Does the CCAR-F exam test MCP specifically or just tool use in general?
People also ask
What is the difference between MCP and function calling in Claude?
Is MCP better than function calling for production agents?
Does MCP replace function calling in the Anthropic API?
How do MCP servers handle authentication compared to function calling?
What are the token costs of using MCP versus inline tools?
About the author
AI Architect & Certification Lead
Solomon Udoh is an AI Architect who designs and ships production agent systems on the Claude API and Claude Code. He built AI Skill Certs' adaptive engine and authored its 174-concept knowledge graph, mapping every Claude Certified Architect - Foundations objective to hands-on, exam-aligned practice.
- Designs production multi-agent systems on the Claude API and Agent SDK
- Author of the AI Skill Certs knowledge graph (174 mapped exam concepts)
- Builds with MCP, Claude Code, structured outputs, and agentic loops daily
- Reviews every concept page against the official Anthropic exam guide
You might also like
Ready to put it into practice?
Study every exam concept with an adaptive tutor.