Agent security guide

MCP security: securing the tools your AI agents call

MCP security is the set of controls that decide which Model Context Protocol servers an AI agent may use, what each tool call may do, and what data comes back. It covers poisoned or changed tool definitions, token rules in the MCP authorization spec, argument- and record-level checks on every tools/call, sandboxed local servers, and inspection of tool output before the model reads it.

What MCP security covers

The Model Context Protocol (MCP) is an open protocol, built on JSON-RPC 2.0, that lets AI applications connect to tools and data in a standard way. An MCP server offers tools, resources and prompts; an MCP client inside a host application, such as a chat assistant or an integrated development environment (IDE), lists those tools and calls them for the model.

MCP security is the practice of controlling which MCP servers an AI agent can use, what each tool call may do, and what the agent receives back. Tool descriptions are text the model reads and trusts. Tool calls carry real authority: sending email, changing records, running commands. Tool results flow straight into the model's context.

The specification is direct about its limits. It states that "MCP itself cannot enforce these security principles at the protocol level" (MCP specification). MCP server security therefore depends on what you build around the protocol.

This page covers the threats, what the current specification (version 2026-07-28, as of October 2026) requires, and the controls that close the gaps. For the wider picture, start with the AI agent security guide.

The MCP threat model

MCP adds attack surface in six places: tool definitions, changes to them, tokens and scopes, local server code, server packages, and the data tools return.

Tool poisoning, shadowing and rug pulls

MCP tool poisoning hides instructions in a tool's description. The user sees a short name; the model reads the full text. In Invariant Labs' April 2025 proof of concept, an add tool told the model to read ~/.ssh/id_rsa and the client's MCP config file, pass their contents in a sidenote argument, and not mention it to the user (Invariant Labs).

The same research showed cross-server shadowing: one server's description changed how the agent used a trusted server's send_email tool, redirecting mail to the attacker. The malicious tool did not need to be called. OWASP lists this class as MCP03 Tool Poisoning in its MCP Top 10, in beta as of October 2026.

A rug pull is a server that behaves well when you review it and changes later. Servers can change their tool list at any time and tell subscribed clients with notifications/tools/list_changed. If approval happened once, at install time, nobody sees the new description or parameter. The update arrives as text the model obeys.

Over-broad scopes, confused deputies and token passthrough

Many MCP servers wrap an API with one powerful key, and every agent that connects inherits all of it. The specification's security guidance names two related failures (MCP security best practices):

  • Confused deputy. An MCP proxy uses one static OAuth client ID with a third-party API. An attacker registers a client with their own redirect URI and sends the user a link. An existing consent cookie skips the consent screen, and the authorization code goes to the attacker.
  • Token passthrough. A server accepts a token that was not issued to it and forwards it downstream. Audience checks, rate limits and audit trails that depend on the token are bypassed, and the server cannot tell clients apart.

Local servers and the server supply chain

A local MCP server is a program on the user's machine, usually started over the stdio transport. It runs with the user's rights: their files, SSH keys, cloud credentials and network. The best-practices page gives examples of malicious startup commands hidden in client configuration, and of localhost servers reached through DNS rebinding.

Red Hat describes researchers finding "many MCP servers bound to 0.0.0.0," reachable from the local network without authentication. It also describes a path-check flaw and a symlink bypass in a filesystem MCP server (CVE-2025-53110 and CVE-2025-53109) that allowed access outside the permitted directories (Red Hat). Servers are installed from package registries, so typosquatting and compromised updates apply too.

Data returned by tools

Tool results go straight into the model's context. A support ticket, a web page or a document can carry instructions written for the agent: indirect prompt injection. Red Hat cites a May 2025 case in which a malicious issue in a public GitHub repository led an assistant to expose data from a private one. Results can also carry data the agent has no need to see, such as national ID numbers in a customer relationship management (CRM) record. NSA's May 2026 MCP guidance makes the same point: treat outputs from tools and models as untrusted by default (NSA).

MCP threats mapped to controls

Threat What it looks like Controls
Tool poisoning A description tells the model to send SSH keys in an extra parameter Review descriptions and parameters before approval; inspect outgoing arguments for secrets
Cross-server shadowing One server's description changes how another server's tool is used Connect each agent only to the servers its job needs; check recipients per call
Rug pull A definition changes after review Pin a hash of each definition; close changed or new tools until re-approved
Over-broad scopes One key, or a files:* token, behind every tool Minimal scopes with step-up; grants per agent and operation
Confused deputy An attacker rides a consent cookie through an MCP proxy Per-client consent; exact redirect URI matching; single-use state
Token passthrough A server forwards the client's token upstream Audience validation; a separate upstream token
Local server compromise Server code runs with the user's rights Show the exact launch command; sandbox with no network
Server supply chain A typosquatted or tampered package Internal registry; pinned versions; inventory
Hostile or sensitive output Injected instructions or unneeded personal data Decode and inspect results; mask fields; hold suspicious documents
State handle hijacking A guessed workflow ID used by another caller Random handles bound to the authenticated user

Most rows need a control outside the model. A system prompt that asks the model to ignore hidden instructions is a request, not a rule.

MCP authorization: what the specification requires

As of October 2026, the current MCP specification is version 2026-07-28. Its authorization chapter is optional and covers HTTP transports. When a server uses it, the rules are specific:

  • The MCP server is an OAuth 2.1 resource server. It MUST publish Protected Resource Metadata (RFC 9728), which tells clients where its authorization server is.
  • Clients MUST send the resource parameter (RFC 8707) with the server's canonical URI, binding each token to one server.
  • Clients MUST use PKCE (Proof Key for Code Exchange), with S256 when technically capable, and MUST validate a returned iss value (RFC 9207) to stop mix-up attacks.
  • Client ID Metadata Documents are the preferred registration method. Dynamic Client Registration is deprecated in this version.
  • Servers SHOULD name required scopes in the WWW-Authenticate header and return 403 with insufficient_scope when a call needs more, so clients step up instead of asking for everything at once.
  • Servers MUST validate that each token was issued for them: "MCP servers MUST NOT accept or transit any other tokens." A server calling an upstream API needs its own token for that API.
  • MCP proxy servers that use a static client ID MUST get user consent for each client before forwarding to a third-party authorization server.

For stdio servers, the spec says implementations SHOULD NOT use this flow and should take credentials from the environment. In practice that means API keys in environment variables or config files, which is why local servers need their own controls.

What OAuth scopes do not decide

A valid token answers one question: may this client call this server, with these scopes? It does not say whether this particular call is reasonable. A crm:write scope allows updating any case, for any customer, at any time. Scopes also record the user's consent, not the agent's job, so two agents acting for the same person get the same reach.

The best-practices page lists a common mistake: "Treating claimed scopes in token as sufficient without server-side authorization logic." Server-side logic means checking the operation, its arguments and the record it touches on every call; see AI agent authorization. Each agent also needs its own identity rather than a shared key.

Controls on each tool call

Three controls apply to every call: check what goes in, know which definition the agent is using, and check what comes back.

Argument- and record-level checks on tools/call

Every tools/call names a tool and passes arguments. Check both before the call reaches the server, in three layers:

  1. Shape. Validate arguments against the tool's inputSchema and reject undeclared properties. This stops invented fields, but not a poisoned tool that declares its own exfiltration parameter, like the sidenote above.
  2. Values. Compare values with the agent's job. A refund has a ceiling. A recipient must be internal. A file path must stay inside the project.
  3. Record. Read the record the call touches. If an assistant acting for Priya asks to update a case, fetch the case and confirm Priya owns it; never trust the agent to state the owner. (Priya works at Northwind, a simulated company used in AgentFort's lab demos.)
# Illustrative per-call policy for one MCP tool (pseudo-syntax)
tool: crm.update_case
agent: personal-assistant
allow_when:
  arguments:
    status: [open, pending, resolved]   # no "deleted"
    undeclared_fields: reject
  record:                               # fetched by the enforcement point, not the agent
    case.owner: equals acting_for.user
otherwise: deny

The tools page of the spec says servers MUST "validate all tool inputs" and "implement proper access controls" (MCP tools). Put the checks where the agent cannot skip them. For money, see spending limits; for calls a person should see first, see human approval.

Pinning and reviewing tool definitions

Treat each tool definition like a dependency. When a person approves a server, store a hash of each tool's canonical JSON: name, title, description, inputSchema, outputSchema and annotations. On every tools/list, recompute and compare. A changed hash closes that tool until someone reviews the diff. A new tool starts closed.

Hashing catches change, not a malicious first version. Review the first version for:

  • Text addressed to the model rather than the user, such as "important", "before using any other tool" or "do not mention".
  • File paths, URLs or other tools' names inside a description.
  • Parameters that do not fit the purpose, such as a free-text field on an arithmetic tool.

Two details matter under the current spec. The result of tools/list may vary with the authorization presented, so fetch and pin with the same identity the agent uses. Clients that combine several servers SHOULD disambiguate tool names, for example with a server prefix, so pin on the disambiguated name. NSA's guidance also advises caution with dynamic tool discovery unless it comes with origin verification or authorization checks.

Inspecting what tools return

Tool output is untrusted input to the model. Inspect it before the model reads it:

  • Validate structuredContent against the tool's outputSchema, which the spec says clients SHOULD do.
  • Decode HTML entities, percent-encoding and base64 before scanning, so hidden text becomes visible.
  • Look for instructions aimed at the agent, and hold the content for review when you find them.
  • Mask fields the agent's job does not need.
  • Cap result size, so a single result cannot flood the context.

The same inspection belongs on arguments going out, where secrets and bulk data leave. AI agent data protection covers detectors, masking and quarantine in detail.

MCP gateways: what they do and what to look for

An MCP gateway is a proxy between agents and MCP servers that applies policy to every message. A typical gateway authenticates each agent, puts several servers behind one endpoint, filters tools/list per agent, decides each tools/call, holds upstream credentials and logs the outcome.

When you evaluate one, ask:

  • Does each agent prove its own identity, or do agents share a key?
  • Can it hide tools an agent does not need from that agent's tool list?
  • Can policy read arguments and fetch the record, or only match tool names?
  • Does it pin tool definitions and close changed or new tools?
  • Does it inspect both directions, after decoding?
  • Does it get its own upstream tokens instead of passing tokens through?
  • Does it refuse calls when its policy service is down?
  • How much latency does it add at your traffic level, measured by you?
  • Does it support the 2026-07-28 protocol and older, handshake-based clients?

Be realistic about coverage. A gateway sees only traffic routed through it; a stdio server on a laptop never touches it. NSA's guidance describes MCP-aware security proxies as limited and still maturing, and calls for caution with sensitive data. An MCP gateway works beside your existing API gateway, not in place of it. AI agent security tools maps the categories.

Securing local MCP servers

Local servers need host controls, because network controls do not reach them.

  • Keep an approved list of servers and versions, installed from an internal registry.
  • Show the exact launch command before a server is added; the best-practices page says clients with one-click setup MUST show it in full and get explicit approval.
  • Run each server in a sandbox: its own user, read access only to the directories it needs, and no network unless the tool requires it, then only to named hosts. See AI agent sandboxing.
  • Keep secrets out of config files. Use short-lived tokens or the operating system's keychain.
  • Prefer stdio for local servers. If one must listen on HTTP, bind it to loopback or a Unix socket and require a token.
  • Find the servers nobody approved. OWASP calls them shadow MCP servers (MCP09). Developer laptops and continuous integration (CI) runners are the usual places; see discovering AI agents.

MCP security checklist

  • Inventory every MCP server, its owner, its version and the agents that use it.
  • Require OAuth with audience-bound tokens for remote servers, and reject tokens issued for anyone else.
  • Replace shared keys with a separate identity and the narrowest scopes for each agent.
  • Validate arguments against the schema and reject undeclared fields.
  • Check argument values and the record each call touches against the agent's job.
  • Pin a hash of every tool definition, and keep changed and new tools closed until reviewed.
  • Inspect tool results and outgoing arguments after decoding.
  • Sandbox local servers with no network and limited file access.
  • Route remote servers through an enforcement point that fails closed.
  • Log every call with identity, tool, decision and reason, without storing payloads. See AI agent audit trails.

How AgentFort handles MCP security

AgentFort Access sits between agents and the services they call, over REST and MCP. An MCP server is registered like any other service: AgentFort suggests how risky each operation is and which fields are sensitive, and the service owner approves. Over MCP, an agent sees only the tools it may use. Every call is checked against the agent's identity, the exact operation, its arguments and the record it touches, which AgentFort reads itself. AgentFort then calls the service with its own credential, scoped to that one operation, so agents never hold the service key. A new tool added by a service stays closed until its owner approves it. AgentFort Data Protection inspects each call in both directions, including tool results. See AgentFort Access, or watch the demo.

Frequently asked questions

Is MCP secure by default?

Not on its own. Authorization is optional in the specification, local servers started over stdio take credentials from their environment and run with the user's rights, and tool descriptions are text that any server author can write. A deployment becomes secure through choices around the protocol: authenticated remote servers, narrow scopes, per-call checks, sandboxed local servers and inspected output.

What is the difference between an MCP gateway and an API gateway?

An API gateway protects HTTP APIs with authentication, rate limits, quotas and routing by path. An MCP gateway understands MCP messages. It can filter the tool list per agent, read the tool name and arguments inside each tools/call, pin tool definitions and inspect results before the model reads them. Many teams run both: the API gateway in front of services, and MCP-aware policy closer to the agents.

Do MCP tool annotations like readOnlyHint make a tool safe?

No. Annotations such as readOnlyHint, destructiveHint, idempotentHint and openWorldHint are hints supplied by the server. The MCP specification says descriptions of tool behavior, including annotations, should be considered untrusted unless they come from a trusted server. Use annotations to sort tools for review, then judge the risk yourself and enforce it with per-call policy.

How do I find MCP servers that nobody approved?

Look where developers configure them: MCP client config files on laptops, IDE settings, CI runners and container images. Watch for processes started by AI clients, and for outbound calls to remote MCP endpoints in proxy or DNS logs. Compare what you find with your approved list. OWASP's MCP Top 10 calls these shadow MCP servers and notes they often run with default credentials and permissive settings.

How should MCP servers handle state now that protocol sessions are gone?

The 2026-07-28 specification removed protocol-level sessions. A server that needs state across calls returns an explicit handle, such as a cart ID, and receives it back as a tool argument. The security guidance says servers must not treat possession of a handle as authentication. Use random, expiring handles, store state keyed to the user ID from the verified token, and reject a handle presented by anyone else.

Sources

See it on your own agents

Put AI agents to work without putting your business at risk.

A working session on your agents: where discovery, identity and enforcement sit in your environment, and the evidence they produce.