MCP security is API security with a new caller, and that caller reads your documentation as instructions. A Model Context Protocol (MCP) server is, in most deployments, an HTTP service that wraps one or more existing APIs, so every API control still applies. What changes is who decides which call to make: a language model choosing tools from natural-language descriptions, carrying arguments it was handed by untrusted content, and acting with a token that may belong to a user who never saw the request. This guide compares the two control by control: what carries over, what breaks and what MCP adds. It is for API platform, application security and identity teams now securing agent tool access.
Key takeaways
- Short answer: MCP security is a superset. Keep every API control (authentication, object-level authorisation, rate limits, schema validation, inventory) and add controls for model-facing text, tool selection, delegated identity and cross-tool data flow.
- The caller is no longer deterministic. An API client sends the requests its developer wrote; an MCP client sends whatever the model chose, so intent is not fixed at build time and must be checked per call.
- Tool descriptions are attack surface. The MCP tools specification says clients must treat tool annotations as untrusted unless they come from trusted servers; descriptions, schemas and tool results all reach the model's context.
- Token passthrough is the signature MCP mistake. The MCP authorisation specification says servers must not accept or transit any tokens not issued for them; upstream calls need their own audience-bound tokens, ideally by OAuth 2.0 Token Exchange.
- Gateways must understand tools, not just paths. A gateway that routes HTTP cannot see which tool, which arguments or which definition version is in play; MCP-aware policy is per tool, per caller and per definition hash.
What is actually different: the caller, the contract and the context
Traditional API security assumes a client written by a developer. The client's behaviour is fixed in code, reviewed in a pull request and changes only when the code is redeployed. Threats come from outside the client: a stolen credential, a tampered request, a malicious user abusing a legitimate client.
MCP changes three things at once.
- The caller: MCP tools are, in the words of the specification, model-controlled, meaning the language model can discover and invoke tools automatically based on its contextual understanding and the user's prompts. Anything that can influence the model, including a document, an email or a previous tool result, can influence which tool is called and with which arguments.
- The contract: an OpenAPI document is read by developers and code generators. An MCP tool definition (name, description, inputSchema, optional outputSchema and annotations) is read by the model at run time and can change: servers that declare
listChangednotify clients when the tool list changes, andtools/listmay return a different set depending on the authorisation presented. - The context: an MCP tool result goes into the model's context window, where free text is indistinguishable from instructions. Indirect prompt injection (OWASP LLM01:2025 Prompt Injection) becomes a delivery route for API abuse.
The API's own authorisation is therefore necessary but not sufficient: a perfectly authorised call can still be the wrong call. See the API Security Guide for the API baseline and the MCP Security Guide for the MCP overview; this page covers the delta.
Side-by-side comparison
| Dimension | API security | MCP security |
|---|---|---|
| Who decides the call | Client code written and reviewed by a developer | A model selecting tools at run time from descriptions and context |
| Contract | OpenAPI or GraphQL schema, versioned with the API | Tool definitions served by tools/list, can change mid-life and vary by caller |
| Main injection channel | Request parameters and bodies (SQL, command, SSRF) | Same, plus tool descriptions, tool results and resources that reach the model |
| Authentication standard | API keys, OAuth 2.0 client credentials or user tokens, mTLS | Optional; for HTTP the MCP authorisation spec profiles OAuth 2.1 with RFC 9728, RFC 8707 and PKCE; stdio servers take credentials from the environment |
| Identity in the request | Usually one client identity, sometimes a user token | A chain: user, host application, MCP client, MCP server, upstream API |
| Characteristic authorisation failure | BOLA and BFLA in the API | Token passthrough, confused deputy at OAuth proxies, over-broad scopes, excessive agency |
| Supply chain | Third-party APIs consumed by code (API10) | Third-party servers installed by users, often running locally with the user's permissions |
| Human control point | None needed at call time | Specification says there should always be a human able to deny tool invocations |
| Audit question | Which client called which endpoint? | Which user, through which agent, asked which tool, with which arguments, based on which definition version? |
Threat model 1: deterministic API clients
Architecture in words: a client application holds a credential (an API key, an OAuth client secret or a user's access token) and calls a fixed set of endpoints through a gateway. The API enforces authentication, then authorisation per object and per function, then business rules.
Threat model and controls: attackers go after the credential (leaked keys, stolen tokens), the server's authorisation logic (changing an object ID, calling an admin route, adding a property), resource limits and URL-fetching features (API7:2023). The answer is standard authentication, deny-by-default authorisation in code, schema validation, rate limits and inventory, all testable because the client is predictable. The McKinsey AI Platform Hack bridges the two worlds: an autonomous agent was the attacker, but what it found were classic API failures, unauthenticated endpoints that built SQL from JSON field names, chained with an insecure direct object reference.
Threat model 2: LLM-driven MCP callers
Architecture in words: a user works in a host application (an IDE, an assistant, an agent platform). The host runs one MCP client per server. Each server exposes tools; a remote server is an OAuth resource server that, in turn, calls upstream APIs with its own credentials or with tokens obtained for the user. The model sees every connected server's tool list and the results of every call in a shared context.
What the attacker targets, in addition to everything in threat model 1:
- Tool poisoning: instructions hidden in a tool's description or schema (ATLAS AML.T0110 AI Agent Tool Poisoning). The model reads them as guidance. See the MCP Tool Poisoning Detection.
- Silent definition changes: a tool approved as harmless is redefined later;
notifications/tools/list_changedhelps only if clients re-review. - Result-borne injection: data returned by a tool carries instructions that trigger the next tool call (AML.T0053 AI Agent Tool Invocation, AML.T0086 Exfiltration via AI Agent Tool Invocation). The Sentry MCP Agentjacking research showed a planted error report, read through an MCP server, leading coding agents to run an embedded package command with the developer's privileges; the server and its API behaved exactly as designed.
- Cross-server flow: one server reads sensitive data, another sends data out; each passes review alone, the combination leaks.
- Credential harvesting: local servers receive API keys through environment variables or configuration files (AML.T0098 AI Agent Tool Credential Harvesting). See the Local MCP Server Security Guide.
- Attacks on the client: the MCP security best practices page describes SSRF during OAuth discovery (a malicious server pointing
resource_metadataat169.254.169.254) andjavascript:or shell-interpreted authorisation URLs. In MCP, the client must also defend against the server.
Why API controls alone miss these: every one of the calls above can carry a valid token, a valid schema and an authorised object. OWASP LLM06:2025 Excessive Agency names the root causes as excessive functionality, excessive permissions and excessive autonomy, none of which an API gateway can see from a single request.
Tool descriptions as attack surface
In API security, documentation is a disclosure concern. In MCP it is an execution concern: the description decides behaviour.
| Artefact | Who can change it | Risk | Control |
|---|---|---|---|
| Description and parameter descriptions | Server author, or anyone who can edit the spec or code annotations it is generated from | Hidden instructions, misleading scope claims | Review as prompt text, hash at approval, alert on change, strip markup |
| inputSchema | Server author | Permissive schemas accept smuggled parameters; free-text fields invite injected content | additionalProperties: false, enums, bounded lengths; server-side validation regardless |
| Annotations (for example read-only or destructive hints) | Server author | A destructive tool labelled harmless bypasses confirmation | Treat as untrusted unless the server is trusted; decide confirmation from your own classification |
| x-mcp-header parameters | Server author | Values mirrored into Mcp-Param-{name} HTTP headers are visible to intermediaries | Never mark secrets or personal data; the spec says servers should not |
| Tool results and structured content | Whoever wrote the underlying data | Indirect prompt injection, oversharing | outputSchema validation (servers must conform when one is declared), field allowlists, restrict tool invocation on untrusted data (AML.M0030) |
The rule that follows: a tool definition is code, with an owner, review, versioning and a hash recorded at approval. The MCP vs OpenAPI Tool Definitions guide covers how to curate tool sets rather than mirror an API.
Identity and tokens: from one caller to a delegation chain
An API request usually carries one identity. An MCP tool call carries a chain: user, host, MCP client, MCP server and the credential the server presents upstream. Each link needs a decision.
What the MCP authorisation specification requires
- Authorisation is optional: HTTP implementations should conform; stdio servers instead retrieve credentials from the environment. Make it required by policy for any remote server.
- Discovery: servers must implement OAuth 2.0 Protected Resource Metadata (RFC 9728) and clients must use it.
- Audience binding: clients must send the
resourceparameter (RFC 8707) naming the server's canonical URI in both authorisation and token requests, and servers must validate that tokens were issued specifically for them. - No passthrough: servers must only accept tokens valid for their own resources and must not accept or transit any other tokens.
- Transport hygiene: tokens go in the Authorization header on every request, never in the query string; invalid or expired tokens get HTTP 401; insufficient scope gets HTTP 403 with
error="insufficient_scope"and the required scopes, which drives step-up.
Requirements checked against the revision dated 2026-07-28 on 14 November 2026; details change between revisions. See the MCP Authorisation Specification Guide.
Token passthrough versus token exchange
Token passthrough is the MCP equivalent of an API gateway that forwards the caller's token unchanged to every backend. The best practices page lists the consequences: audience-dependent controls are bypassed, downstream logs show the wrong identity, and a stolen token can be replayed through the server. The fix is the same one mature API platforms use for service-to-service calls: obtain a new token for each hop. OAuth 2.0 Token Exchange (RFC 8693) supports delegation, where the acting party keeps its own identity and the issued token records it in an act claim, as distinct from impersonation, where the actor becomes indistinguishable from the subject. For agent traffic, delegation is the right default because it preserves who asked and who acted. See OAuth Token Exchange vs Token Passthrough.
The confused deputy at OAuth proxies
A specific MCP pattern has no common API equivalent. An MCP server that fronts a third-party API with a single static client ID, while letting MCP clients register dynamically, can be abused if the third-party authorisation server remembers consent in a cookie, letting an attacker-registered client receive the user's authorisation code without a fresh consent screen. The specification requires per-client consent on a server-owned page, exact redirect URI matching and single-use state values set only after consent.
Scopes designed around tools
Design MCP scopes around tool risk rather than resources: a minimal baseline (the specification's example is mcp:tools-basic) for discovery and reads, with step-up challenges for privileged tools. The best practices page lists the common mistakes: every scope in scopes_supported, wildcard scopes, the full catalogue in every challenge, and treating token scopes as sufficient without server-side authorisation logic.
Gateway controls: API gateway versus MCP-aware gateway
An API gateway still does useful work for remote MCP servers (TLS, authentication, coarse rate limits, logging), but without MCP awareness it cannot reason about the JSON-RPC payload. Every tool call to a Streamable HTTP server may arrive at the same path, so a path-based rule sees one endpoint where there are fifty tools.
| Control | API gateway (path-aware) | MCP-aware gateway |
|---|---|---|
| Authentication | Validates token signature, issuer, expiry | Same, plus audience equals the canonical MCP server URI; rejects foreign tokens |
| Authorisation | Per path and method | Per tool name, per caller, per argument pattern; filters tools/list to what the caller may use |
| Change control | New routes appear on deploy | Hashes each tool definition, blocks or flags changes until re-approved |
| Credential handling | Forwards or strips the inbound token | Brokers upstream credentials so agents never hold backend secrets; performs token exchange per hop |
| Logging | Client, path, status, latency | User, agent, client ID, tool, definition hash, redacted arguments, decision, correlation ID |
Two cautions: a gateway concentrates credentials, so harden it like an identity provider, and it does nothing for local stdio servers on developer laptops, which never cross it; those need endpoint controls and configuration scanning. See MCP Gateway vs Direct MCP Connections and AI Gateway vs API Gateway.
Worked scenario: exposing a ticketing API to an internal agent
A support platform team runs a mature ticketing API: OAuth client credentials for integrations, user tokens for the web app, object-level checks on every ticket, a gateway with rate limits. They are asked to let an internal assistant read and update tickets through MCP.
- The tempting design: wrap the API in a remote MCP server, generate one tool per operation, configure the server with the existing integration's client credentials and let the assistant call it. API security review passes: every call is authenticated and authorised.
- What goes wrong: the integration credential can read every ticket, so object-level checks pass for everything and the user's own permissions are ignored. Ticket bodies are written by customers; one contains instructions to export recent tickets and post them to an external webhook tool the assistant also has. The bulk export operation was generated as a tool because it existed in the spec. No log shows which employee's request led to the export.
- The MCP-aware design: curate five task tools (search own queue, read ticket, add comment, change status, escalate) and exclude export and admin operations. Require OAuth audience-bound to the server's canonical URI. Exchange the user's token for a ticketing API token with an
actclaim naming the MCP server, so the API enforces that user's permissions and logs both identities. Require confirmation for status change and escalation, pin tool definitions, and block the session from combining the ticketing server with any external-send tool (AML.M0029, AML.M0030). - Result: the API's existing controls now see a real user, each new attack path has a specific control, and the audit trail answers who asked, which agent acted and which tool version ran.
When API security is enough, and when it is not
- API controls are largely enough when: the server exposes a small, read-only tool set over low-sensitivity data, with no user delegation and no external-send tools in the same session. Add definition pinning.
- MCP-specific controls are mandatory when: any tool writes, deletes, pays, sends or administers; the server acts for individual users; tool results include outsiders' text; several servers share a session; or servers run locally.
- Small versus large organisations: small teams start by banning passthrough, removing static secrets from MCP configuration, keeping an approved server list and confirming write tools. Large organisations make API platform teams own the MCP servers for their APIs, publish curated catalogues and route remote MCP traffic through an MCP-aware gateway.
Where identity fits
Every MCP server is a non-human identity twice over: an OAuth client registered with an authorisation server, and a holder of credentials to the APIs it wraps; the agent adds the identity on whose behalf it acts. Inventory all three with owners and expiry, and prefer short-lived, audience-bound tokens per hop over API keys in configuration. See API Keys vs OAuth for MCP Servers.
How to extend an API security programme to MCP
- Inventory: add MCP servers (remote and local) to the API inventory with owner, wrapped APIs, credential type, tool count and data classification. Scan developer endpoints and repositories for MCP configuration files. Use the MCP Server Inventory Template.
- Classify tools: mark each tool read, write, destructive, external-send or administrative; this classification, not server annotations, drives confirmation and scope design.
- Fix identity: require OAuth on remote servers, enforce audience validation, remove passthrough, introduce token exchange for upstream calls, and design minimal baseline scopes with step-up.
- Pin definitions: record a hash of every approved tool definition; alert on change and require re-approval.
- Pilot in observe mode: log gateway decisions without blocking for two to four weeks and compare tools exposed with tools used.
- Enforce: switch to blocking per team, with a documented rollback to observe mode and a per-tool kill switch that does not require redeploying agents.
- Test: extend API testing scope to description and result injection, cross-server flows and OAuth proxy consent. See the MCP Security Testing Guide.
Detection and measurement
Log, for every tool call: user, agent or host, MCP client ID, server, tool name, definition hash, redacted arguments, upstream token audience, decision and correlation ID. The tools specification says clients should log tool usage for audit. Alert on wrong-audience tokens, definition changes outside a release, write tools called straight after reading external content, and new servers on endpoints.
| Metric | What it shows | Target |
|---|---|---|
| Passthrough rate | Upstream calls made with a token whose audience is not the upstream API | Zero |
| Authorised remote servers | Remote MCP servers that require OAuth with audience validation | 100% |
| Unreviewed definition changes | Tool definition hashes changed without re-approval | Zero |
| Confirmation coverage | Write, destructive and external-send tools that require human approval | 100% |
| Exposure ratio | Tools exposed divided by tools used in 30 days | Close to 1 |
Common failure patterns
- Declaring MCP "just another API": the server passes API review, but nobody reviews descriptions, results or tool combinations.
- Forwarding the user's identity provider token: convenient, explicitly forbidden, and it destroys the downstream audit trail.
- One integration credential behind every tool: object-level checks pass for every object, so the agent sees what the integration sees, not what the user may see.
- Ignoring local servers: remote servers are governed while local stdio servers with personal access tokens run unreviewed on laptops.
Framework mapping
| Concern | API reference | MCP and agent reference | NIST SP 800-53 Rev 5 |
|---|---|---|---|
| Object and function authorisation | API1, API5:2023 | LLM06:2025 Excessive Agency | AC-3, AC-6 |
| Authentication and token validation | API2:2023 | MCP authorisation spec (audience, no passthrough) | IA-9 |
| Injection via descriptions and results | API10:2023 | LLM01:2025; ATLAS AML.T0110, AML.T0053 | SI-10 |
| Inventory of servers and tools | API9:2023 | ATLAS AML.M0028 Enforce Access Controls for AI Agent Tools | CM-8 |
Practitioner checklist
- Add every MCP server, remote and local, to the API inventory with owner, wrapped APIs and credential type.
- Require OAuth with RFC 8707 audience binding on every remote server; reject tokens issued for anything else.
- Remove token passthrough; use token exchange with delegation so upstream APIs see the user and the acting server.
- Classify each tool by risk and require confirmation for write, destructive and external-send tools.
- Hash and pin tool definitions; treat any change as a code change needing review.
- Validate inputs server-side and outputs against outputSchema; never pass model-generated values to shells or queries.
- Design minimal baseline scopes with step-up instead of omnibus scopes.
- Block risky server combinations in one agent session, especially sensitive read plus external send.
- Log user, agent, tool, definition hash and decision for every call; review the metrics monthly.
Standards and references
- Model Context Protocol: Authorization specification
- Model Context Protocol: Security Best Practices
- Model Context Protocol: Tools specification
- OWASP: API Security Top 10 2023
- OWASP: Top 10 for LLM Applications 2025
- IETF: RFC 8693 OAuth 2.0 Token Exchange
- IETF: RFC 8707 Resource Indicators for OAuth 2.0
- MITRE: ATLAS
Related NHI Mgmt Group resources: MCP Security Guide · API Security Guide · Remote MCP Server Hardening Guide · MCP Gateway and MCP Server Governance Guide