MCP Security Best Practices
An MCP server can read your data and act on your behalf, so the risks come from three places: a server that is malicious or buggy, instructions hidden in content the model reads (tool descriptions, web pages, emails, files), and credentials that get handled badly. The MCP security best practices page and the tools specification say what servers, clients and apps must and should do. As a user, keep a person approving sensitive tool calls, read what a local server will run, and check a server before you install it. As a builder, validate every input, accept only tokens issued to your server, and enforce limits in your code.
Where the risks come from
Most MCP attacks take one of three routes, and the defences line up with them.
The first route is a server that does something you didn't ask for, either because it was built to or because it has a bug. The second is text the model reads: a tool description, or the output of a tool, can carry instructions that the model follows. The third is trust that goes too far. A server that accepts a token meant for someone else, or a client that fetches any address a server hands it, lets one party act with another's authority.
Local servers add a fourth case. A local server is a program on your computer, and the spec says it can run any command your user account can.
The risks at a glance
| Risk | What it looks like | Read more |
|---|---|---|
| Tool poisoning | A tool description contains instructions for the model that the app may not show you. Invariant Labs published this in April 2025. | Tool poisoning and rug pulls |
| Rug pulls | A server changes a tool's description after you have approved it. | Tool poisoning and rug pulls |
| Prompt injection | Text a tool returns, such as a web page, email or file, tells the model to call another tool. | Prompt injection |
| Token passthrough and confused deputy | A server accepts a token that wasn't issued to it, or passes it on to another API. | Common MCP vulnerabilities |
| SSRF | A client fetches an address a malicious server gave it, such as a cloud metadata endpoint. | Common MCP vulnerabilities |
| Local server compromise | A local server runs a command you didn't read, with your user's privileges. | Sandbox local servers |
| Over-broad scopes | A token can do far more than the task needs, so one leak does more damage. | Authorization and OAuth |
What the spec requires
The spec uses MUST and SHOULD with specific meanings. A MUST is a requirement a compliant implementation has to meet. A SHOULD is the expected behaviour, with reasons to deviate only in unusual cases. These are the security requirements that apply to you.
Servers MUST:
- validate all tool inputs,
- implement proper access controls,
- rate limit tool invocations,
- sanitize tool outputs (from the tools specification),
- never accept a token that wasn't explicitly issued for the server (from the security best practices).
Clients and apps SHOULD:
- always keep a human in the loop who can deny a tool call,
- prompt for user confirmation on sensitive operations,
- show tool inputs to the user before calling the server,
- validate tool results before passing them to the model,
- time out tool calls and log tool usage.
Two more apply to clients. Clients MUST treat tool annotations as untrusted unless they come from a trusted server. And if a client offers one-click setup for a local server, it MUST show the exact command, without truncation, and get explicit approval before it runs.
Checklist for people using MCP servers
- Connect only the servers you use, and turn off or remove the rest.
- Before a local server starts, read the full command it will run. If your app shows only part of it, don't approve it until you've seen the rest.
- Keep your app asking before sensitive tool calls. Check that it shows the tool's inputs, not just its name, before you approve.
- Re-check a server after it updates. A tool's description can change after you approved it.
- When a server sends you to sign in, check that the sign-in page is the provider's own site.
- Check a server before you install it. The evaluate MCP servers checklist covers publisher, permissions and source.
Checklist for people building MCP servers
- Validate every input against your own rules, not only the schema. The schema tells the client what shape to send, and your code decides what to accept.
- Check authorization on every request. A state handle or ID that a client sends back is not proof of who is calling.
- Accept only tokens issued to your server. Don't pass a client's token on to an upstream API. The spec explicitly forbids token passthrough.
- Ask for the smallest set of scopes the operation needs, and request more when a specific operation needs it.
- Rate limit tool calls, and sanitize tool output before you return it. The model reads what you return, so treat it as input to another system.
- Keep tool descriptions to what the tool does. Instructions aimed at the model, or text meant to make it hide actions, belong nowhere in a description.
- For local servers, use the stdio transport so that only the client can reach the server. If you use HTTP instead, require an auth token or use a local socket with restricted access.
- If you use the
x-mcp-headerannotation on Streamable HTTP, don't put passwords, API keys or personal data in the parameters you mirror. The spec says header values are visible to network intermediaries.
Annotations are hints, not controls
Tool annotations such as readOnlyHint describe what a tool should do, but the spec says clients must treat them as untrusted unless they come from a trusted server. A tool marked read-only can still write, so a read-only annotation protects you only if the server enforces it in code. The tool annotations guide covers the fields in detail.
Stateful servers and state handles
MCP itself has no sessions. A server that needs state across calls, such as a shopping basket or a workflow, returns an ID that the model sends back as an ordinary argument. The 2026-07-28 security page calls the attack on this pattern state handle hijacking: an attacker obtains or guesses the ID and uses it on someone else's state. The spec's rule is that possession of a handle is never authentication, and that handles should be random and tied to the authenticated user. For the older session IDs used by the 2025-11-25 revision, the page's 2025-11-25 version describes session hijacking.
Common misconceptions
"A local server can't hurt me because it never leaves my computer." A local server runs as a program with your user account's privileges. It can read the files and run the commands that account can.
"Read-only annotations mean the tool is safe." Clients must treat annotations as untrusted, so the server has to enforce the behaviour itself.
"I approved this server, so it's still the same server." A server can change a tool's description after approval. This is what the rug pull research describes.
"OAuth means the server is safe." OAuth gives the server a token. The server still has to check that the token was issued for it. A server that accepts any valid token has the token passthrough problem, whatever sign-in flow it used.
Scanners and open references
Two open projects help you check servers. SAFE-MCP is a framework for documenting and mitigating threats in the AI agent ecosystem, and you can use its list of threats as a checklist. mcp-scan from Invariant Labs scans AI agents, MCP servers and agent skills. Use either as a starting point. A scan that finds nothing doesn't prove that a server is safe.
For a worked example of how one product applies checks to tool definitions, read how we score MCP server security.
FAQ
Is MCP secure?
MCP is a protocol, and its security depends on the server you connect, the app you connect it from, and how you set up the connection. The spec sets requirements for both servers and clients, and most of the risk comes from what a server is allowed to reach.
Are local MCP servers more dangerous than remote ones?
They are dangerous in different ways. A local server runs as a program on your computer with your user account's privileges. A remote server holds the data it can reach and often a token for it, so the risk is in what it does with them and who else can call it.
Should I approve every tool call?
For sensitive actions, yes. The spec says a person should always be able to deny a tool call, and apps should confirm sensitive operations. Read the inputs before you approve, because the name of a tool doesn't tell you what it will send.
Does signing in with OAuth make a server safe?
It helps, but only if the server checks that each token was issued to it. A server that accepts any valid token from another service can be used to reach data you didn't intend to share.
- Common MCP vulnerabilitiesConfused deputy, token passthrough, SSRF and session hijacking, with the fixes the spec describes.
- Tool poisoning and rug pullsHidden instructions in tool descriptions, and how definitions can change after approval.
- Prompt injectionHow text in tool results can steer the model, and how to limit the damage.
- Sandbox local serversLimit what a local server can read, write and reach on your machine.
- Check a server before you install itA checklist of what to look at before you connect a server.