MCP Security Best Practices
MCP servers run as local processes with the permissions you grant them. A poorly-configured or malicious server can read files, exfiltrate data, or execute arbitrary code. This guide covers how to evaluate servers before installing them and how to limit blast radius if something goes wrong.
Threat model
Before installing any MCP server, it helps to understand what it can actually do. An MCP server runs with the operating-system permissions of the user who launched Claude Desktop — typically your full user account. That means:
- A filesystem server can read any file your account can read — including SSH keys, browser profiles, and credential stores.
- A network-capable server can make outbound requests to arbitrary hosts.
- A server that spawns subprocesses can run any binary on your system.
- Environment variables passed in the config are readable by the server process.
This is not inherently dangerous — it is by design, since usefulness requires access. The goal is to grant only the access each server legitimately needs.
Server verification and trust
Not all MCP servers are equal. Use the following criteria to evaluate a server before adding it to your config:
Source repository
Prefer servers with a public GitHub repository. Read the source — for most npm packages it is short enough to review in 10 minutes. Look for outbound network calls in unexpected places.
Publisher identity
Servers published under @modelcontextprotocol, @anthropic, or well-known vendor namespaces (@supabase, @cloudflare, @stripe) carry more trust than anonymous packages. Check the npm registry for publish history and author.
Download volume and age
A package with millions of weekly downloads and years of history is harder to compromise without detection than a new package with no history. This is not a guarantee, but it raises the bar for supply-chain attacks.
Dependency surface
Run npm ls in the package to see the full dependency tree. A server with 200 transitive dependencies has a much larger attack surface than one with 5.
Servers on this directory marked Verified are official releases from the named vendor or Anthropic. Community servers are listed without endorsement — apply additional scrutiny.
Permission scoping
Most MCP servers accept arguments that limit their scope. Always pass the narrowest scope that meets your needs.
Filesystem — restrict to specific directories:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/projects/myapp"
]
}
}
}GitHub — use a fine-grained PAT with minimal scopes:
# Create a fine-grained PAT at github.com/settings/personal-access-tokens # Grant only: # - Contents: Read-only (for read operations) # - Issues: Read and write (if you need issue management) # - Pull requests: Read and write (if needed) # Scope to specific repositories, not "All repositories"
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "github_pat_..."
}
}
}
}Sandboxing strategies
For servers from untrusted authors, consider running them in a sandboxed environment. Options in order of increasing isolation:
Dedicated user account
Low effortCreate a separate macOS/Linux user with access only to the directories the server needs. Launch Claude Desktop as that user. Prevents access to your primary home directory.
Docker container
Medium effortRun the MCP server inside a Docker container with volume mounts limited to specific paths and no host network access. Pass the socket path to Claude Desktop via the command field.
VM or devcontainer
High effortRun Claude Desktop inside a development container or lightweight VM. Full network and filesystem isolation. Suitable for servers that handle sensitive data in regulated environments.
Prompt injection via tool output
A less-obvious attack vector: a malicious server (or a compromised data source) can return content that contains instructions aimed at the AI model. For example, a web page fetched by the Fetch server might contain a hidden <!-- IGNORE PREVIOUS INSTRUCTIONS --> comment.
Claude has defenses against prompt injection, but they are not absolute. To reduce risk:
- Do not ask Claude to fetch and act on content from untrusted URLs in a single step.
- Review tool call results before asking Claude to act on them when working with external data.
- Use servers that return structured data (JSON, typed results) rather than raw HTML where possible.
- Enable Claude's built-in tool-call confirmation prompts in Claude Desktop settings.