A third-party MCP server is a piece of code someone else wrote that you connect to your workspace. Once connected, Claude can call its tools — which means the server can read files, run commands, hit APIs, or do anything else its tool handlers do. The convenience is real: a Notion MCP server lets Claude search your Notion pages without you writing the integration. The risk is also real: a malicious or sloppy MCP server is a privileged guest in your workspace, and the threat model is not fully understood by most people who install one.
This article is a practical checklist for what to verify before installing a community MCP server. It does not require security expertise — most of the checks are reading the code and asking the right questions.
What can a malicious MCP server actually do?
The honest answer: depends on its tools and your permission setup. A read-only server that just returns weather data has a small blast radius. A server that exposes a "run any shell command" tool, registered in a permissive workspace, can do whatever you can do at the terminal — including reading ~/.ssh/, writing to disk, exfiltrating files over the network, or installing persistent malware.
The risks roughly cluster into five categories:
- Direct exfiltration — server tools that read sensitive paths and ship the contents to a remote endpoint
- Confused deputy — server uses your authenticated session (e.g. an API token) to take actions you didn't intend, often via a tool that "helpfully" acts on Claude's behalf
- Prompt injection — server fetches external content (web pages, support tickets, emails) and surfaces it as tool output, where attacker-controlled instructions ride along into Claude's reasoning
- Supply chain — the server itself is fine, but one of its dependencies is compromised; you inherit the dependency's behaviour
- Overprivileged tools — a tool advertised as "read a file" actually reads any file the server can access; or a "format JSON" tool that quietly executes arbitrary code
The audit checklist
Run through these before adding any server to ~/.claude.json or .mcp.json. None of the checks require special tools — a text editor, npm, and patience are enough.
1. Provenance
- Where does the source live? GitHub repo, npm package, both?
- Is the maintainer identifiable? Same person across the repo, npm, and any docs?
- How long has the repo existed? A repo created last week with no commit history is a different risk than one with three years of activity
- Is it a fork of something else? If so, why? What did the fork add or remove?
- How many stars, contributors, open issues? Not proof of safety, but a long-active project with engaged users tends to surface problems faster
2. Dependency surface
Look at package.json — what does the server pull in?
- Run
npm ls --allafter install to see the full dependency tree - Watch for typosquatting — packages with names a single character off from popular ones (
requesst,lodassh) - Watch for outdated dependencies with known CVEs —
npm auditis a quick first pass - Watch for unusual dependencies that don't fit the server's stated purpose — a "weather" server pulling in a crypto-mining library is a flag, obviously, but the same logic applies to less obvious mismatches
3. Tool definitions
Open the source. Find every server.registerTool(...) call (or equivalent) and read the schema and handler.
- What does each tool actually do? Match the description against the implementation — not the README
- Does any tool execute arbitrary input — shell commands, SQL queries, file paths without validation, or runtime code generation primitives?
- Does any tool fetch URLs? If so, are URLs constrained to specific domains or open to anything?
- Does any tool read files? If so, is the path validated, or can a tool call read
~/.ssh/id_rsa? - Are there tools that look unrelated to the server's stated purpose? "Note-taking" servers don't need shell execution
4. Network behaviour
- Search the source for
fetch(,axios,http.,https.— every outbound call - Where do those calls go? An MCP server for a specific service should only call that service's API
- Anything calling a domain you don't recognise? Look it up before installing
- Does the server transmit anything at startup or on a schedule, independent of tool calls? Telemetry can be benign or invasive — read what's sent
5. Environment and filesystem access
- Search for
process.envreads — what env vars does the server expect, and what would happen if it could read every env var on your machine? - Search for
fs.calls — what paths does the server read or write, and are those paths constrained? - Search for
child_process,execSync,spawn— does the server shell out, and to what?
6. Code integrity signals
- Obfuscated or minified source in a place that should be readable (the published source on GitHub, not
node_modulesoutput) is a flag - Use of
evalon input from anywhere — flag - Dynamic constructor-based code generation with computed inputs — flag
- Dynamic
require()with computed paths — flag - Files that don't match the project's stated stack (a TypeScript project with a single bundled
.jsfile claiming to be the source)
The questions to answer before you install
Once the checks are done, you should be able to answer:
- Who wrote this and how long has it been public?
- What permissions does it actually need, and does it ask for more than that?
- Where does it send data, and is that the right place?
- If this server is compromised tomorrow, what's the worst it can do given how I'll register it?
- Is there an official version maintained by the service this server wraps?
The last question matters more than people think. If you want a Notion MCP server, the official Notion-maintained one is a different risk profile than a community fork. Pick the official version unless there is a specific reason not to.
Reducing blast radius after install
Even after auditing, treat MCP servers like any third-party code:
- Don't store secrets the server doesn't need. If a server only needs read access to one API, give it a token scoped to that
- Run Claude Code in
defaultpermission mode (notbypassPermissions) so destructive tool calls require approval - Keep audit logs — Claude Code's session JSONL files record every tool call, including MCP calls, so you can review what happened later
- Pin versions in your config (
npm install pkg@1.2.3) so a malicious update doesn't get pulled in silently - Re-audit on major version bumps; a v2 release is a chance for new tool capabilities to appear
When in doubt
If a server fails any of the checks and you can't get a satisfying answer, don't install it. The friction of writing your own thin wrapper around an API you actually understand is almost always less than the cost of cleaning up after a bad MCP server. The previous article walks you through writing one in under 100 lines of code.
