MCP Security Best Practices: A Field Guide for 2026

MCP security best practices come down to four controls: accept only tokens issued to your server, treat every tool description and tool result as untrusted input, keep a human able to deny sensitive calls, and log every invocation with its full parameters. The Model Context Protocol specification and the OWASP cheat sheet both point to these as the core defences.
This guide is for the security, platform and engineering leads who are connecting AI agents to real systems through MCP servers. It goes through the threats the specification itself names, the attacks researchers have shown in practice, and a checklist you can apply to any MCP deployment this week. Every requirement below is quoted from a primary source and linked, so you can check the wording yourself.
Key takeaways
- Authorization is optional in MCP, so it is your job to add it. The authorization specification says plainly that "Authorization is OPTIONAL for MCP implementations." Remote servers that touch business data need it anyway.
- Token passthrough is forbidden. An MCP server must not accept tokens that were issued for another service, and must not forward the token it received to a downstream API.
- Tool descriptions are an attack surface. Tool poisoning, rug pulls and cross-server shadowing all work by hiding instructions in text the model reads and the user never sees.
- Approval does not last. A tool approved today can change its definition tomorrow. Pin and hash reviewed tool definitions, and review them again whenever they change.
- Evidence is part of security. If you cannot reconstruct which agent called which tool, with which arguments, for which user, you cannot investigate an incident or answer an auditor.
What is MCP security?
MCP security is the set of controls that stop a Model Context Protocol deployment from being used to steal credentials, run unintended code, or take actions a user never approved. MCP connects a model to tools and data through servers. The tools specification describes tools as "model-controlled, meaning that the language model can discover and invoke tools automatically based on its contextual understanding and the user's prompts."
That design choice is what makes MCP useful, and it is also the core of the risk. In a normal application, a developer decides which API call runs. With MCP, the model decides, based on text that may come from a user, a document, a web page or another tool. Anything that can influence that text can influence which tool runs and what arguments it gets.
MCP security therefore covers three layers:
- Identity and tokens: who the server thinks is calling, and which credentials it uses downstream.
- Tool integrity: whether the tool definitions and tool results the model reads can be trusted.
- Execution and evidence: where the server runs, what it can reach, who can stop a call, and what record each call leaves.
Why do MCP security best practices matter now?
MCP security best practices matter because MCP servers sit between a model that can be manipulated and APIs that hold real data and real permissions. A single compromised or careless server can turn a prompt injection into a data leak or a destructive write.
The protocol leaves much of this to implementers. The OWASP MCP Security Cheat Sheet notes that "Authorization is optional in the protocol" and that MCP "does not require every JSON-RPC message to be signed." Many controls in the specification are SHOULD statements directed at client and server authors, not rules the protocol enforces on the wire. If you run MCP in production, your deployment is only as safe as the choices you make on top of the protocol.
The attacks are no longer theoretical. In April 2025, Invariant Labs showed a poisoned tool getting Cursor to leak the user's mcp.json configuration file. In a second test, a malicious tool's description redirected a trusted email tool: "The Cursor agent sends all emails to the attacker, even if the user explicitly specifies a different recipient."
What are the main MCP security risks?
The main MCP security risks are confused deputy attacks, token passthrough, server-side request forgery, local server compromise, over-broad scopes, and the family of tool-poisoning attacks. The first five are named in the specification's own security best practices; the last is documented by Invariant Labs and OWASP.
| Risk | What happens | Primary control |
|---|---|---|
| Confused deputy | A proxy MCP server uses its own trusted client identity to get a third-party token on behalf of an attacker | Per-client consent before forwarding to third-party authorization servers |
| Token passthrough | A server accepts a token issued for another service and forwards it downstream | Validate the token audience; never forward the client's token |
| SSRF | A client is induced to fetch internal or cloud-metadata URLs during OAuth discovery | HTTPS only, block private IP ranges, validate redirect targets |
| Local server compromise | A one-click local server install runs an attacker's command with the client's privileges | Show the exact command and require explicit approval |
| Over-broad scopes | One stolen token unlocks everything | Progressive, least-privilege scopes; no wildcard scopes |
| Tool poisoning | Hidden instructions in a tool description steer the model | Review and pin tool definitions; treat descriptions as untrusted |
| Rug pull | A tool's definition changes after the user approved it | Hash pinned definitions and re-review on change |
| Cross-server shadowing | One server's tool text changes how the agent uses another server's tools | Isolate servers; treat each as an independent trust domain |
The specification gives scope design a short warning that is worth quoting in full: "Poor scope design increases token compromise impact, elevates user friction, and obscures audit trails."
How do you stop token passthrough and confused deputy attacks?
You stop token passthrough by having every MCP server check that each access token was issued to that server, and by never forwarding the client's token to a downstream API. The security best practices define token passthrough as "an anti-pattern where an MCP server accepts tokens from an MCP client without validating that the tokens were properly issued to the MCP server and passes them through to the downstream API."
The authorization specification (2025-11-25) turns that into hard requirements:
- Validate the audience. "MCP servers MUST validate that access tokens were issued specifically for them as the intended audience."
- Reject everything else. "MCP servers MUST NOT accept or transit any other tokens."
- Never forward the client's token. "The MCP server MUST NOT pass through the token it received from the MCP client." If the server needs to call a downstream API, it obtains its own token for that API.
- Name the target resource. Clients "MUST implement Resource Indicators for OAuth 2.0 as defined in RFC 8707," and must send the resource parameter "regardless of whether authorization servers support it."
- Use PKCE with S256. Clients "MUST implement PKCE" and "MUST use the
S256code challenge method when technically capable." - Keep tokens out of URLs. "Access tokens MUST NOT be included in the URI query string."
The confused deputy problem arises when an MCP server acts as an OAuth proxy to a third-party API using a single static client ID. An attacker can ride on consent the user gave earlier. The fix in the specification is consent per client: "MCP proxy servers using static client IDs MUST obtain user consent for each dynamically registered client before forwarding to third-party authorization servers."
A practical test: pick any token your MCP server accepts and ask which audience it was minted for. If the answer is "the downstream SaaS API" rather than "this MCP server," you have token passthrough.
How do you defend against tool poisoning, rug pulls and shadowing?
You defend against tool poisoning by treating every tool description, schema and tool result as untrusted input, and by pinning the exact tool definitions a person reviewed. Invariant Labs defines the attack this way: "A Tool Poisoning Attack occurs when malicious instructions are embedded within MCP tool descriptions," instructions that are invisible to users but visible to AI models. It is a form of indirect prompt injection; for the wider family of attacks, see our guide to prompt injection and emerging prompt-based attacks.
Two variants make this worse:
- Rug pull: "a malicious server can change the tool description after the client has already approved it." Approval at install time proves nothing about the tool you are running today.
- Shadowing: "A malicious server injects a tool description that modifies the agent's behavior with respect to a trusted service or tool." Invariant's conclusion was that "the shadowing attack is enough to hijack the agent's behavior with respect to trusted servers." Your trusted servers are only as safe as the least trusted server connected to the same agent.
The controls, from the OWASP cheat sheet and the specification:
- Pin and hash. "Pin reviewed tool definitions using cryptographic hashes and require review when they change."
- Watch for changes. "Monitor for changes to tool descriptions post-installation (rug pull detection)."
- Isolate servers. "Treat each MCP server as an untrusted, independent security domain."
- Distrust annotations. The tools specification says "clients MUST consider tool annotations to be untrusted unless they come from trusted servers." A tool that calls itself read-only may not be.
- Distrust results too. OWASP: "Treat every tool response as untrusted data, including responses from approved servers." A tool that fetches a web page or a support ticket returns attacker-controlled text.
How should you sandbox and run MCP servers?
You should run each MCP server with only the files, network access and credentials its job needs, and never let a client launch a local server without showing the exact command. Local servers are the sharpest edge: the specification lists the risk as "Arbitrary code execution. Attackers can execute any command with MCP client privileges."
For local servers, the specification requires clients that offer one-click setup to "Show the exact command that will be executed, without truncation (include arguments and parameters)" and to "Require explicit user approval before proceeding." It recommends that local servers "Use the stdio transport to limit access to just the MCP client."
For remote and containerised servers, apply what OWASP lists under sandboxing and least privilege:
- "Restrict file system access to only required directories."
- "Use scoped, per-server credentials — never share tokens across servers."
- Request narrow scopes, for example
mail.readonlyinstead ofmail.modify.
Network egress deserves its own rule. The specification's SSRF section says clients "SHOULD block requests to private and reserved IP address ranges" and that operators "SHOULD consider using an egress proxy that enforces network policies." An MCP server that can reach your cloud metadata endpoint can hand over your cloud credentials.
When should a human approve an MCP tool call?
A human should approve any MCP tool call that writes, deletes, sends, pays or exposes data outside its current boundary, and should always be able to deny any call. The tools specification states: "For trust & safety and security, there SHOULD always be a human in the loop with the ability to deny tool invocations."
The same page asks clients to show tool inputs "to the user before calling the server, to avoid malicious or accidental data exfiltration," and to "Prompt for user confirmation on sensitive operations." OWASP is blunter: "Never auto-approve tool calls, especially in multi-server setups."
Approval only works if it is specific. A prompt that says "Allow Slack?" is consent theatre. A useful approval shows the tool, the exact arguments, the user the agent is acting for, and what system it will change. If you want to go deeper on designing approvals that a security reviewer can defend, our note on why agentic compliance runs on immutable evidence covers what should be captured at the moment of approval.
What should an MCP audit log record?
An MCP audit log should record every tool invocation with its full parameters, the user and agent it ran for, the server and tool name, a timestamp, and the outcome. OWASP's monitoring control says to "Log all MCP tool invocations with full parameters, user context, and timestamps," and the tools specification asks clients to "Log tool usage for audit purposes."
Two details decide whether the log is useful in an incident:
- Write before you act. A log written after the call misses the calls that crashed, timed out or were killed halfway. Record the intent (tool, arguments, user) before the call goes out, then the outcome after.
- Make edits evident. A log an administrator can quietly edit is a story, not evidence. Chaining entries by hash means any later change breaks the chain and shows up on verification.
This is the design behind Receipt, Kentron's hosted agent platform: its gateway writes an intent receipt with the tool, arguments, requesting user and workspace before each governed call, and if that write fails, the call does not happen. Receipts form SHA-256 hash chains, so tampering is evident to a verifier. Coding agents such as Claude Code, Codex and Cursor reach connected apps through Receipt's hosted MCP server, so the same record covers them.
The DEPTH checklist for MCP deployments
The DEPTH checklist is a five-part review you can run against any MCP server before it goes near production data. Each letter maps to one failure class from the sections above.
| Letter | Check | Pass condition |
|---|---|---|
| Definitions pinned | Are tool definitions reviewed, hashed and re-reviewed on change? | Any change to a description or schema blocks the tool until a person approves it |
| Egress limited | Can the server reach only the hosts it needs? | Private ranges and metadata endpoints blocked; egress proxy in place |
| Permissions scoped | Does each server have its own narrow credentials? | No shared tokens, no wildcard scopes, writes off by default |
| Tokens bound | Does the server accept only tokens minted for it? | Audience checked on every request; no token passthrough |
| Human and history | Can a person deny sensitive calls, and is every call recorded first? | Specific approval prompts; intent logged before execution, tamper-evident |
Score each row pass or fail. A server with any failing row should not get write access to a business system.
Worked example: securing a CRM MCP server
Consider a team that connects an agent to its CRM through a remote MCP server so sales can ask for account summaries and log call notes.
- Tokens. The team registers the MCP server as its own OAuth resource. The client requests tokens with the server as the resource indicator. The server rejects any token whose audience is not itself, then uses its own credential to call the CRM API. Token passthrough is gone.
- Scopes. Read access to accounts is granted to everyone; writing notes is a separate scope granted only to the sales group. No
full-accessscope exists. - Definitions. The two tools,
get_accountandadd_note, are reviewed and their definitions hashed. A nightly job compares the live definitions against the hashes and disables the server on mismatch. - Results. Account notes can contain text written by customers, so the client treats every
get_accountresult as untrusted data and never lets it trigger a new tool call without the user seeing it. - Approval and record.
add_noteshows the user the exact note and account before it runs. Each call writes an intent record first and an outcome record after, chained by hash.
Before go-live, the team also tries to break it on purpose, using the approach in red teaming: the art of thinking like an adversary: a poisoned note, a swapped tool description, and a token minted for the CRM itself. Run DEPTH against the result: definitions pinned, egress limited to the CRM host, permissions scoped, tokens bound, human approval plus history. Five passes.
What are the most common MCP security mistakes?
The most common MCP security mistakes are skipping authorization because the protocol makes it optional, forwarding user tokens downstream, granting wildcard scopes, and trusting a tool because it was approved once.
- "It's internal, so no auth." Internal servers are exactly what SSRF and confused deputy attacks reach.
- Wildcard scopes. The specification lists "Using wildcard or omnibus scopes (
*,all,full-access)" among the common scope mistakes. - One-time approval. Rug pulls exist because approval is checked once and the tool keeps changing.
- Mixing trusted and untrusted servers in one agent. Shadowing means the weakest server sets the security level for all of them.
- Logging after the fact. Post-hoc logs miss the calls you most need to see.
When is MCP the wrong choice?
MCP is the wrong choice when the action is high-risk, fixed and rarely changes, such as a scheduled payment run or a production database migration. There, a reviewed script with fixed inputs is easier to secure than a model choosing tools at runtime. MCP earns its place when the set of useful actions is broad and the request is phrased in natural language. Even then, start read-only and add write tools one at a time, each with its own scope and approval.
FAQ
What are the most important MCP security best practices? Accept only tokens issued to your MCP server and never forward a client's token downstream. Treat tool descriptions and tool results as untrusted, pin reviewed definitions, keep a human able to deny sensitive calls, and log every invocation with full parameters.
Is authentication required in the Model Context Protocol? No. The MCP authorization specification states that authorization is optional for MCP implementations, and stdio servers are told to take credentials from the environment instead. Any remote MCP server that touches business data should still require OAuth-based authorization.
What is tool poisoning in MCP? Tool poisoning is an attack where malicious instructions are hidden in an MCP tool's description, schema or results, where the model reads them but the user usually does not. Invariant Labs demonstrated it in April 2025 by getting Cursor to leak a user's MCP configuration file.
What is an MCP rug pull attack? An MCP rug pull is when a server changes a tool's definition after the user approved it, turning a trusted tool malicious. The defence is to hash the reviewed definition and block the tool until someone reviews any change.
What is token passthrough and why is it banned? Token passthrough is when an MCP server accepts a token that was issued for another service and forwards it to a downstream API. The MCP authorization specification forbids it because it breaks audience checks, accountability and rate limiting; the server must get its own token instead.
Should every MCP tool call need human approval? No, but a person should always be able to deny any call, and calls that write, send, delete or move money should show the exact arguments for approval. Read-only calls on low-risk data can run without a prompt as long as they are logged.
What should an MCP audit log contain? It should contain the server and tool, the full arguments, the user and agent the call ran for, a timestamp and the outcome. Write the intent before the call and the outcome after, and chain entries by hash so any later edit is evident.