Teams wiring tools into AI agents often treat the Model Context Protocol (MCP) and native function calling as interchangeable, yet they put the trust boundary, the credentials and the code in very different places. Native function calling is a feature of a model API: the model returns a structured request to call a function you declared, and your application runs it. MCP is an open protocol that lets a host application connect to separate servers that publish tools, resources and prompts, often written and run by someone else. This guide compares the two from a security point of view, explains when to use each, and lists the controls each one needs. It is for security architects, platform engineers and AppSec teams reviewing agent designs. The MCP details reflect the current specification revision, 2026-07-28, checked on 13 November 2026.
Key takeaways
- Short answer: they solve different problems. Function calling is how a model asks for a tool; MCP is how tools are packaged, discovered and connected across process and organisation boundaries. Many hosts use function calling internally to drive MCP tools.
- The trust boundary moves with MCP. With native function calling your own code runs the tool. With MCP a server you may not control supplies the tool name, description and schema, and executes the call.
- Tool metadata is untrusted input. The MCP specification says tool annotations should be considered untrusted unless they come from a trusted server, so descriptions can carry injected instructions (tool poisoning).
- Identity is the deciding control. Remote MCP servers use OAuth-based authorisation with audience-bound tokens and a ban on token passthrough; native function calling inherits whatever credentials your application holds.
- Both need the same runtime guardrails. Least functionality, schema validation, human approval for high-impact actions and full logging of every tool call apply whichever pattern you choose.
What each one is
Native function calling
Function calling (also called tool use) is a capability of the model API. Your request includes a list of tool definitions, each with a name, a description and a JSON Schema for its parameters. When the model decides a tool is needed it returns a structured call, your application executes it and sends the result back, and the model continues. The model never runs code itself. Providers document this pattern in similar terms (listed alphabetically):
- Anthropic (Claude API): the model returns a
tool_useblock, your application returns atool_resultwith the matching ID;tool_choicecan beauto,any,toolornone, andstrict: truemakes calls match the input schema exactly. - Google (Gemini): functions are declared in OpenAPI schema format; the model returns a function call, your application executes it and returns a function response, and parallel calls are answered together.
- OpenAI: functions are declared in a
toolsarray with JSON Schema parameters and astrictflag; the model returns calls linked bycall_idand your application returns one output per call.
Model Context Protocol
MCP is an open protocol using JSON-RPC 2.0 between three roles: hosts (the LLM application), clients (connectors inside the host) and servers (services that provide context and capabilities). Servers expose resources, prompts and tools; clients can offer elicitation, a server-initiated request for more information from the user. Tools are discovered with tools/list and invoked with tools/call. Transports are stdio, where the client launches the server as a local subprocess, and Streamable HTTP for remote servers. The 2026-07-28 revision makes requests stateless and self-contained with per-request capability negotiation, replacing the initialisation handshake used by 2025-11-25 and earlier revisions. See the MCP Security Guide for the protocol in depth.
The two meet in practice: a host typically converts the tools it learns from MCP servers into function definitions for its model, so the model uses function calling and the host uses MCP to reach the tool. Some model APIs also offer a built-in connector to remote MCP servers, which moves the MCP client into the provider's platform.
Side-by-side comparison
| Dimension | Native function calling | MCP |
|---|---|---|
| What it is | A model API feature for structured tool requests | An open client-server protocol for tools, resources and prompts |
| Who defines the tool | Your application, in the API request | The MCP server author, returned by tools/list |
| Who executes the tool | Your application code (or provider-hosted tools) | The MCP server process, local or remote |
| Trust boundary | Inside your application; the model output is the untrusted input | Between host and server; model output, tool metadata and tool results are all untrusted |
| Credentials | Held by your application or its workload identity | stdio: from the environment; HTTP: OAuth access tokens bound to the server as audience |
| Discovery and change | Static, versioned with your code | Dynamic; servers can send notifications/tools/list_changed |
| Portability | Tied to one provider's request format | One server works with any compliant host |
| Supply chain exposure | Your code and its libraries | Third-party servers, packages and registries |
| Consent model | Whatever your application builds | Specification requires explicit user consent before invoking any tool and a human able to deny calls |
| Typical fit | A single application with a few well-known internal functions | Many agents or hosts sharing tools, or tools owned by other teams or vendors |
Where the trust boundaries sit
With native function calling there is one boundary that matters most: the model's output. The arguments in a function call are generated text, so a prompt injection in the conversation or a retrieved document can shape them. Your application is both the policy decision point and the executor, which makes it straightforward to validate arguments, check the end user's entitlements and refuse calls before they run.
MCP adds at least two more boundaries:
- Host to server: the server supplies tool names, descriptions and schemas that are placed in the model's context. A malicious or compromised server can hide instructions there, or change a tool after approval through a list change. This is AML.T0110 AI Agent Tool Poisoning in MITRE ATLAS. See MCP Tool Poisoning Detection.
- Server to downstream system: the server calls APIs and data stores with its own credentials. If it accepts tokens issued for another audience, or forwards the token it received, it becomes a confused deputy. The specification forbids token passthrough and requires servers to accept only tokens issued for them. See the Confused Deputy in AI Agents Guide.
- Local process boundary: a stdio server runs with the user's privileges on the user's machine. The security best practices say clients offering one-click configuration must show the exact command without truncation and require explicit approval, and should sandbox servers with minimal default privileges. See the Local MCP Server Security Guide.
Security risks compared
| Risk | Native function calling | MCP | Primary control |
|---|---|---|---|
| Prompt injection steering tool arguments (OWASP LLM01:2025) | Present | Present, plus injection through tool descriptions and results | Argument validation, approval for high-impact calls, AML.M0030 Restrict AI Agent Tool Invocation on Untrusted Data |
| Excessive agency (OWASP LLM06:2025) | Too many functions or over-privileged service credentials | Servers exposing more tools or scopes than the task needs | Least functionality, scope minimisation, per-tool allowlists |
| Tool poisoning and rug pulls | Low, definitions live in your code | High where servers are third-party or change dynamically | Pin server versions, review and hash tool definitions, alert on list changes |
| Token misuse | Application secrets in code or environment | Token passthrough, wrong audience, broad scopes, stolen local tokens | RFC 8707 resource indicators, audience validation, short-lived tokens |
| SSRF | Only if a function fetches user-chosen URLs | OAuth discovery URLs supplied by a server can target internal addresses such as 169.254.169.254 | HTTPS only, block private and link-local ranges, egress proxy |
| Local code execution | Not inherent | stdio servers and malicious startup commands | Show exact command, sandboxing, signed or allowlisted packages |
| Data exfiltration via tools (AML.T0086) | Through any outbound function | Through any server, including a cross-server chain | Egress control, data classification on tool outputs, logging |
When to use each
- Choose native function calling when one application owns a small, stable set of functions, the code runs in your environment, and you want a single place to enforce authorisation. It is the simpler, smaller attack surface. One provider's guidance suggests keeping the number of functions available at the start of a turn small, under about 20.
- Choose MCP when the same tools must serve several hosts or agents, when a SaaS provider or another team owns the tool, or when users need to add integrations without code changes. Accept that you are now running an integration platform and govern it like one.
- Use both, which is the common case: internal functions for core business actions, MCP for shared or third-party integrations behind a gateway. See the MCP Gateway and MCP Server Governance Guide.
- Small organisations: prefer native function calling or a short allowlist of vetted MCP servers; do not let staff install arbitrary local servers.
- Large organisations: run an internal registry of approved MCP servers with owners, a gateway for remote servers, and the same identity platform issuing tokens for both patterns.
Where identity fits
Every tool call acts as some identity, and the two patterns hide that differently. With native function calling the function usually runs as the application's service account or workload identity, so a broad role silently extends to every user and every prompt. With remote MCP the server is an OAuth resource server: the client requests a token with the resource parameter naming the server, the server validates the audience, and any downstream API needs a separate token issued to the server. Local stdio servers take credentials from the environment, which often means long-lived API keys on laptops. Treat every MCP server and every function's backing credential as a non-human identity with an owner, an inventory entry and a review date. See the Agent Identity and Access Guide and MCP Static Token Audit.
How to implement: a phased approach
- Inventory: list every function exposed to a model and every MCP server configured in hosts, IDEs and agent platforms, with owner, transport, credentials and data reached. The MCP Server Inventory Template gives a format.
- Classify actions: mark each tool read-only, write, destructive or external-send. Destructive and external-send tools require human approval (AML.M0029 Human In-the-Loop for AI Agent Actions).
- Lock definitions: for functions, keep schemas in code review with strict schema mode and
additionalProperties: false. For MCP, pin server versions, record a hash of each tool definition at approval and alert when it changes. - Fix identity: replace shared keys with per-tool, least-privilege credentials; for remote MCP require audience-bound OAuth tokens, PKCE and minimal initial scopes with step-up for privileged operations.
- Pilot in log-only mode: route tool traffic through a gateway or middleware that logs and evaluates policy without blocking, for two to four weeks, and tune.
- Enforce: switch policy to blocking for one host or team at a time. Keep a rollback switch that returns the gateway to log-only, and a kill switch that disables a single server or function without redeploying the agent.
- Review: recertify servers, scopes and function lists quarterly and after any provider or server version change.
Detection and measurement
Log, for every call: the agent and end-user identity, host, server or function name, definition version or hash, arguments (redacted where sensitive), result size, decision (allowed, approved, denied) and correlation ID. The MCP tools specification says clients should log tool usage for audit purposes and servers must rate limit invocations. Watch for tool list changes, calls to tools never seen in a session before, new outbound domains, 401 and 403 spikes with insufficient_scope, and stdio servers launching shells or network tools.
- Inventory coverage: percentage of configured MCP servers and exposed functions with a named owner and approval record.
- Approval coverage: percentage of destructive or external-send tools that require human confirmation.
- Static credential count: number of servers or functions still using long-lived keys, trending to zero.
- Definition drift: unreviewed tool definition changes detected per month.
- Denied call rate: share of tool calls blocked by policy, with a target of investigating every spike.
- Scope breadth: average number of scopes per MCP token compared with the minimum needed.
Common failure patterns
- Treating MCP as just function calling: teams review the model integration but never the third-party server that supplies tool descriptions and runs the code.
- Trusting tool results: output returned by an MCP server is model input. In the Sentry MCP Agentjacking 2026 research, a planted error report read through an MCP server was treated as instructions by coding agents running with the developer's own credentials.
- Token passthrough: an MCP server forwards the user's token to a downstream API, breaking audit trails and letting stolen tokens be replayed through the server.
- One god credential: a single service account with write and delete rights backs every function, so any injected call has full reach, the classic OWASP LLM06 excessive permissions case.
- Approving once, trusting forever: a server is approved, then its tool list changes and nobody re-reviews it.
- Requesting every scope: clients ask for all of
scopes_supportedand servers publish omnibus scopes, which the specification lists among common mistakes. - Local servers on 0.0.0.0: an HTTP server meant for one developer listens on all interfaces without authentication or Origin validation, exposing it to the network and to DNS rebinding.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| OWASP Top 10 for LLM Applications 2025 | LLM01 Prompt Injection; LLM06 Excessive Agency | Argument manipulation; over-broad tools, permissions and autonomy |
| MITRE ATLAS | AML.T0053 AI Agent Tool Invocation; AML.T0110 AI Agent Tool Poisoning; AML.T0098 AI Agent Tool Credential Harvesting | Abuse of tools and their metadata and credentials |
| MITRE ATLAS mitigations | AML.M0029; AML.M0030; AML.M0032 Segmentation of AI Agent Components | Approval, untrusted-data restrictions, isolation of servers |
| NIST SP 800-53 Rev 5 | AC-6 Least Privilege; CM-7 Least Functionality; SI-10 Information Input Validation; AU-12 Audit Record Generation; SA-9 External System Services; SR-3 Supply Chain Controls and Processes | Scoping, validation, logging, third-party servers |
| NIST CSF 2.0 | ID.AM-02; PR.AA-05; PR.PS-04 | Inventory of servers and functions, least-privilege access, logging |
Practitioner checklist
- Inventory every exposed function and configured MCP server with an owner and data scope.
- Decide per tool whether it belongs in your code (function) or behind MCP, and record why.
- Enforce strict schemas and validate every argument server-side before execution.
- Require human approval for destructive and external-send tools in both patterns.
- Pin MCP server versions, hash approved tool definitions and alert on list changes.
- Use audience-bound, short-lived tokens for remote MCP; never pass tokens through.
- Sandbox local stdio servers and bind any local HTTP server to localhost with authentication.
- Route remote MCP traffic through a gateway that logs identity, tool, arguments and decision.
- Replace long-lived keys behind functions and servers with workload identity where possible.
- Recertify servers, scopes and function lists quarterly.
Worked scenarios
The scenarios below are illustrative examples, not real incidents.
Native function calling scenario: an internal ticket assistant. An engineering team adds three tools to its assistant: search tickets, read a ticket and add a comment. The tool definitions live in the application code, strict schema validation is on, and each call runs with the signed-in user's token rather than a shared service credential. Adding a comment needs the user to confirm the text first, and every tool call is logged with the user, tool name and arguments.
MCP scenario: connecting a third-party documentation server. A team wants its coding assistant to use a vendor's remote MCP server for documentation lookups. Before approval, the security team reviews the server's tool names and descriptions as untrusted input, pins the approved tool list, and confirms the server uses OAuth with tokens bound to its own audience and no token passthrough. When a later server update changes a tool description to include instructions to read local files, the pinned list blocks the changed tool until it is reviewed again.
Standards and references
- Model Context Protocol: Specification 2026-07-28
- Model Context Protocol: Security Best Practices
- Model Context Protocol: Tools (2025-11-25)
- Model Context Protocol: Authorization (2025-11-25)
- OWASP: Top 10 for LLM Applications 2025
- Anthropic: Tool use with Claude
- Google Cloud: Introduction to function calling
- OpenAI: Function calling
Related NHI Mgmt Group resources: AI Agent Tool and Plugin Security Guide · MCP Security Best Practices Explained · MCP Server Trust Assessment · Agentic AI Security Guide