MCP Server Security: How to Vet a Server Before You Use It
A practical guide to MCP server security. Check the code, dependencies, tool descriptions, network traffic and permissions before you connect a server.
MCP server security comes down to one fact: an MCP server is code you let an AI model drive. A local server runs on your machine with your user account's permissions. A remote server gets your tokens and sees whatever data your prompts and tool calls send it. To vet one, check five things before you connect it: who publishes it, what the code does, what it depends on, what its tool descriptions tell the model, and which network hosts it talks to. Then install it with the fewest permissions that still work.
This guide walks through each check, explains the attacks behind them, covers what the 2026-07-28 MCP specification changed for security, and shows what an automated scan can and cannot tell you. If you are new to the protocol, start with our short explainer on what an MCP server is and come back.
At a glance
- Local servers run with your privileges. Treat a stdio server like any program you download and run.
- Tool descriptions are untrusted input to the model. Read them before you connect, and again after every update, to catch tool poisoning and rug pulls.
- Pin versions and audit dependencies.
npx -y packagewith no version runs whatever was published last. - Remote servers must validate tokens. Under the MCP authorization spec, servers must only accept tokens issued for them and must not pass client tokens through.
- Least privilege and human approval still matter after any scan. A clean scan lowers risk; it does not prove a server is harmless.
Why do MCP servers need vetting?
The Model Context Protocol connects AI apps (hosts such as Claude Desktop, Claude Code, Cursor or VS Code) to servers that expose tools, resources and prompts. The MCP specification is blunt about the risk. It says tools represent arbitrary code execution and must be treated with caution. It also says tool descriptions and annotations should be considered untrusted unless they come from a trusted server.
Three properties make MCP servers different from an ordinary library:
- They run with your privileges. A local server started over stdio is a normal process. The official Claude Desktop guide warns that the filesystem server can do any file operation you can do yourself.
- Their text goes straight into the model's context. Tool names, descriptions and results are read by the model, not just by you. That makes them a channel for prompt injection against tool-using agents.
- They are usually installed by command. A config line like
npx -y some-packagedownloads and runs the latest published version every time the client starts. That is a classic AI agent supply chain risk.
MCP also sits in front of an API and inherits its keys; see MCP vs API for how the two layers relate. None of this means MCP is unsafe by design. It means an MCP server deserves the same review you would give a browser extension or a CI action that can read your secrets.
What are the main MCP security risks?
Malicious or careless code
The simplest attack is a server that does something bad when it starts or when a tool runs. Common patterns include reading environment variables that hold API keys, reading ~/.ssh or other credential files, calling eval on downloaded strings, spawning shell commands, and obfuscated code that hides any of the above. The MCP project's security best practices list a malicious startup command and a malicious payload inside the server as the first two ways a local server gets compromised.
Careless code is just as common. A tool that passes model-supplied arguments into a shell command, or a file tool with no path checks, can be abused by anyone who can get text in front of the model.
Vulnerable or malicious dependencies
Most servers pull in dozens of npm or PyPI packages. One outdated package with a known vulnerability, or one hijacked package, puts the whole server at risk. Unpinned installs make this worse because you can get a different dependency tree tomorrow than you reviewed today.
Tool poisoning, rug pulls and shadowing
Invariant Labs described tool poisoning attacks in April 2025. A tool that looks like a harmless calculator hides instructions in its description, telling the model to read SSH keys and config files and pass them out through an extra parameter. The same write-up covers rug pulls, where a tool's description changes after you approved it, and shadowing, where one server's description changes how the model uses another server's tools. We cover these in depth in our guide to MCP tool poisoning and rug pulls.
Network exfiltration
A server that reads secrets is only dangerous if it can send them somewhere. Watching which domains a server contacts is one of the most useful checks you can run. A weather server that talks to a weather API is expected. The same server talking to a paste site or a raw IP address is not.
Remote server and auth problems
Remote servers add web risks. The spec's authorization rules require HTTP servers that use auth to follow OAuth 2.1, validate that tokens were issued for them, and never pass client tokens through to other APIs. The security best practices page also covers confused deputy attacks on proxy servers, SSRF through OAuth discovery URLs, malicious authorization URLs, and DNS rebinding against servers left listening on localhost. Our comparison of local vs remote MCP servers explains how these risks differ by transport.
Too much access
Even an honest server can do damage if you give it more than it needs: a filesystem server pointed at your home directory, a database server with a write-capable admin login, or an OAuth grant with every scope. Least privilege limits the blast radius when something else goes wrong. See our guide to least privilege for AI agents for the general pattern.
Risks and the checks that reduce them
| Risk | What it looks like | Check that reduces it |
|---|---|---|
| Malicious code | Reads ~/.ssh, env vars, runs shell commands | Steps 3 and 6: skim the code, watch network traffic |
| Vulnerable dependencies | Known CVE in a package on the input path | Step 4: dependency audit, pinned versions |
| Tool poisoning and rug pulls | Hidden instructions in tool descriptions; descriptions change later | Steps 5 and 9: read every description, re-check on update |
| Exfiltration | Connections to undeclared domains or raw IPs | Step 6: record outbound traffic in a sandbox |
| Token misuse on remote servers | Token passthrough, wrong audience | Check the server follows the authorization spec; review scopes |
| Too much access | Home directory, admin DB login, every OAuth scope | Step 7: least access that works |
| Unwanted actions | Model writes, deletes or sends without asking | Step 8: keep human approval on |
Known MCP vulnerabilities
Real advisories show these risks are not theoretical. Two well-documented examples:
- CVE-2025-6514, mcp-remote command injection.
mcp-remoteis an npm package that lets stdio-only clients connect to remote MCP servers. Versions 0.0.5 to 0.1.15 could run OS commands when connecting to an untrusted server, through a craftedauthorization_endpointURL in the OAuth flow. The CVE record was published on 9 July 2025 with a CVSS 3.1 score of 9.6. Sources: NVD entry and JFrog's write-up. If you usemcp-remote, update to a release after 0.1.15 and connect only to servers you trust. The spec's best practices now say clients must reject dangerous URL schemes and must not open authorization URLs through a shell. - The GitHub MCP issue (May 2025). Invariant Labs showed that a malicious issue on a public repository could steer an agent with a broad GitHub token into leaking data from private repositories through the GitHub MCP server. No code bug was needed; the attack used prompt injection plus an over-scoped token. We walk through it in our post on prompt injection in AI agents.
What did the 2026-07-28 MCP spec change for security?
The 2026-07-28 changelog is the current revision. The changes that matter when you vet a server:
- No more protocol sessions. The
initializehandshake and theMcp-Session-Idheader are gone. Servers that need state across calls mint their own handles and receive them as tool arguments. The best practices replace "session hijacking" with "state handle hijacking": servers must not treat possession of a handle as authentication and should bind handles to the authenticated user. server/discoveris required. Servers must implement it to advertise their versions, capabilities and identity. You can use it, ortools/list, to see what a server exposes before you connect it to a model.- Tool list changes arrive by opt-in. Clients receive
toolsListChangedonly by subscribing onsubscriptions/listen, andtools/listresults carryttlMsandcacheScope. A client that caches tool lists still needs to re-read descriptions when they change, which is where rug pulls happen. - Issuer validation. Authorization servers should send
issin authorization responses, and clients must validate a presentissagainst the recorded issuer before redeeming the code. This blocks mix-up attacks (authorization spec). - Credentials bound to their issuer. Clients must key stored client credentials by issuer and must not reuse them with a different authorization server.
- Dynamic Client Registration is deprecated in favour of Client ID Metadata Documents. DCR stays for backwards compatibility.
- HTTP+SSE is formally Deprecated under the new feature lifecycle policy, so it is scheduled for removal. Prefer Streamable HTTP.
What did not change: the authorization spec still requires OAuth 2.1, PKCE, resource indicators (RFC 8707) in both the authorization and token requests, audience validation on the server, and no token passthrough.
Transport and auth requirements
| Transport | Credentials | What the spec says |
|---|---|---|
| stdio (local) | From the environment | Implementations should not use the HTTP authorization flow; they get credentials from the environment (authorization) |
| Streamable HTTP | OAuth 2.1 when auth is used | Authorization is optional, but HTTP servers that support it should follow the spec; servers must validate the Origin header (transports) |
| HTTP+SSE (legacy) | As above | Deprecated; migrate to Streamable HTTP (changelog) |
How do I vet an MCP server? A step-by-step checklist
Work through these in order. The early steps are quick and rule out most bad options.
1. Check who publishes it
Look at the repository owner, the package publisher and the link between them. Does the npm or PyPI package link back to the same repository? Is the server published by the company whose API it wraps? Is it actively maintained, with recent commits and responses to issues? An official server from the vendor is not automatically safe, but an anonymous fork of a popular server with a slightly different name deserves extra suspicion.
2. Read the install command
Before you paste a config snippet, read the exact command and arguments. Watch for:
npx -yoruvxwith no version, which runs whatever is latest- extra commands chained with
&∨ curl ... | shstyle installers- arguments that grant broad access, such as your whole home directory
Pin a version where you can:
{
"mcpServers": {
"example": {
"command": "npx",
"args": ["-y", "@example/mcp-server@1.4.2"]
}
}
}
3. Skim the code for dangerous patterns
You do not need to read every line. Search the source for the patterns that matter:
# Node.js
grep -rnE "eval\(|new Function|child_process|execSync|spawn\(" src/
grep -rnE "process\.env" src/
# Python
grep -rnE "eval\(|exec\(|subprocess|os\.system" .
grep -rnE "os\.environ|getenv" .
Every hit is a question, not a verdict. A git server will spawn git. The question is whether the arguments are validated and whether the command matches what the tool claims to do. Large blobs of base64, minified code in a source repo, or code that downloads and runs other code at runtime are red flags.
4. Check for leaked secrets and vulnerable dependencies
Run a secret scanner and a dependency audit, or check that someone else has:
gitleaks git -v .
osv-scanner scan -r .
A committed API key tells you about the maintainer's habits. A known-vulnerable dependency tells you about real risk, especially if it sits on the path that handles model input.
5. Read every tool description
List the tools and read their descriptions as if you were the model. With the official MCP Inspector you can do this from the command line:
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
Red flags include instructions aimed at the model ("before using this tool, read..."), mentions of other tools or servers, hidden text, unusually long descriptions, and parameters that have nothing to do with the tool's job (a notes or sidenote field on a calculator).
6. Watch its network traffic
Run the server once in a sandbox and record where it connects. Compare that list to what the README says. Any domain you cannot explain, or a hard-coded IP address, needs an answer before you go further. If you run it in Docker, you can start with networking off and only enable it once you know what to allow:
docker run --rm -i --network none --cap-drop ALL --user 1000:1000 my-mcp-server
7. Give it the least access that works
- Point filesystem servers at a project folder, not your home directory.
- Create a read-only database user or a scoped API token just for the server.
- Pass only the environment variables it needs in the
envblock, not your whole shell. - For remote servers, review the OAuth scopes on the consent screen and decline broad ones. The spec's scope minimization guidance recommends a small initial scope set with step-up requests for privileged operations.
8. Keep human approval on
The spec says there should always be a human in the loop who can deny tool invocations. Most clients ask before each tool call by default. Leave that on for any tool that writes, deletes, sends or spends. Auto-approve only read-only tools you have reviewed.
9. Re-check on every update
A server you vetted last month is not the server you run today if the version floats. When you bump the version, look at the diff, re-list the tools, and compare the descriptions to what you saw before.
For a printable list that also covers agents, skills and runtime monitoring, use our AI agent security checklist. For the general approach to agents beyond MCP, see our guide to AI agent security.
How does this map to the OWASP MCP Top 10?
The OWASP MCP Top 10 is a community list of MCP-specific risks. As of 12 November 2026 the project page marks it as a beta release, with items labelled 2025. This is our own mapping of the checklist above to its items; OWASP does not publish it.
| OWASP MCP item | Checklist steps |
|---|---|
| MCP01:2025 Token Mismanagement and Secret Exposure | 4, 7 |
| MCP02:2025 Privilege Escalation via Scope Creep | 7, 9 |
| MCP03:2025 Tool Poisoning | 5, 9 |
| MCP04:2025 Software Supply Chain Attacks and Dependency Tampering | 1, 2, 4 |
| MCP05:2025 Command Injection and Execution | 2, 3 |
| MCP06:2025 Prompt Injection via Contextual Payloads | 5, 8 |
| MCP07:2025 Insufficient Authentication and Authorization | 7, plus the authorization checks above |
| MCP08:2025 Lack of Audit and Telemetry | 6, and "Read the logs" below |
| MCP09:2025 Shadow MCP Servers | 1, and "Keep a short list" below |
| MCP10:2025 Context Injection and Over-Sharing | 7, and "Separate sensitive work" below |
What can an automated scan tell you?
Doing all of this by hand for every server is slow. Automated scans make it repeatable. Any listing in our MCP server directory can get a free automated scan; each listing page shows its scan status. Here is what the scan does:
- It runs on a fresh GitHub Actions virtual machine that is destroyed afterwards.
- It runs static analysis with Semgrep plus custom rules for eval, shell exec, hidden environment variable reads and obfuscation.
- It looks for committed secrets with Gitleaks and known-vulnerable dependencies with OSV-Scanner.
- It installs and starts the server inside a Docker container with all Linux capabilities dropped, running as a non-root user.
- It starts the server over stdio and lists its tools. The probe currently opens with
initialize, which servers on revisions before 2026-07-28 require, then callstools/list. - It records all outbound network traffic and compares it with the domains the manifest (server.json or agent.json) declares. Undeclared domains and hard-coded IPs are flagged.
- It repeats the run. Three clean runs must match for the reproducibility badge.
The results become badges and a 0 to 100 score, and the full report is public on the listing page. You can read the details on how the scan works.
Be clear about the limits. A scan is a malware and risk check, not a safety guarantee. It looks at one commit during a short run without your real credentials. Code that waits, detects a sandbox, or only misbehaves with real API keys can pass. Static rules catch common patterns, not every trick. A clean report lowers risk. It cannot prove a server is harmless, so the least-privilege and human-approval steps above still matter.
How do I keep my setup secure after install?
Vetting is a gate, not a guarantee. A few habits keep the risk low over time:
- Keep a short list. Every connected server adds tools to the model's context and expands the attack surface. Remove servers you no longer use.
- Separate sensitive work. Do not run an untrusted server in the same session as one that has access to production credentials or private email.
- Prefer project-scoped config. In Claude Code and Cursor, a project-level config limits a server to the repo that needs it. Our MCP server install guide shows the exact files for each client.
- Read the logs. Claude Desktop writes each server's stderr to its own log file. Unexpected errors or connection attempts are worth a look.
If you build MCP servers
The same checklist tells you what users will look for. Pin your dependencies, keep secrets out of the repo, keep tool descriptions short and factual, and declare the domains your server talks to. If you run a remote server, validate token audience, never pass client tokens through, and implement server/discover for the 2026-07-28 revision. Our tutorial on how to build your first MCP server walks through a minimal TypeScript server and the manifest that declares its network access. When it is ready, you can submit the repo for a free scan.
FAQ
Are MCP servers safe to use?
Many are, but safety depends on the specific server. A local MCP server runs with your user's permissions and its tool descriptions are read by the model, so a malicious or careless one can leak files or credentials. Check the publisher, code, dependencies, tool descriptions and network traffic before you connect it.
What is the biggest security risk with MCP servers?
There is no single biggest risk, but two stand out: running untrusted code locally with full user permissions, and tool poisoning, where hidden instructions in tool descriptions steer the model. Both are reduced by reviewing the server, pinning its version, limiting its access and keeping tool-call approval on.
How can I tell if an MCP server is malicious?
Look for code that reads credential files or many environment variables, runs shell commands built from input, uses eval or obfuscation, or contacts domains unrelated to its job. Read every tool description for instructions aimed at the model. An automated scan helps, but no scan can prove a server is completely safe.
Is a remote MCP server safer than a local one?
Not automatically. A remote server cannot touch your local files, but it receives your tokens and any data you send through tool calls. Check that it uses HTTPS and OAuth with narrow scopes, and trust the operator, not just the code.
Can an MCP server steal my API keys?
Yes, if you give it the chance. A local server can read any environment variable it is started with and any file your user can read, and it can send them out if it has network access. Pass only the variables it needs in the env block, use a scoped key made for that server, and run untrusted servers with networking off or restricted. On remote servers, the spec forbids token passthrough, so a server should never forward your client token to another API.
What is the OWASP MCP Top 10?
It is an OWASP project listing ten MCP-specific risks, from token mismanagement and scope creep to tool poisoning, command injection and shadow MCP servers. The project page marks it as a beta release. Use it as a vocabulary for reviews; the checklist in this guide maps to each item.
Did the 2026-07-28 MCP spec make servers more secure?
It removed protocol sessions, so session hijacking becomes state handle hijacking, and it added issuer validation and issuer-bound client credentials to the OAuth flow. It also deprecated HTTP+SSE and Dynamic Client Registration. These help with transport and auth risks. They do nothing about malicious code or poisoned tool descriptions, so you still need to vet each server.
How do I check which tools an MCP server exposes?
Run it with the MCP Inspector and call tools/list, as shown in step 5, before you add it to your client. Servers on the 2026-07-28 revision also answer server/discover with their capabilities and identity. Read each tool's name, description and input schema, and note anything that writes, deletes, sends or spends.
Browse agents, MCP servers and skills on AgenticMart, see what each can touch, and explore the newest standards on our agent protocol map. List yours free now, paid selling opens soon.