On this page
Your MCP config file lists every server your agent can start and what each
one gets. Scan it in two passes. First read it by hand for five risks:
unpinned versions, tokens in env, servers that shell out, plain-HTTP remotes
and broad access. Then grade every server in it with one prompt.
The two passes catch different things. The hand check covers how you set servers up. The grade covers the servers themselves. Neither one replaces the other.
Where each client keeps its MCP config file
| Client | MCP config file | Servers are under |
|---|---|---|
| Claude Desktop | macOS: ~/Library/Application Support/Claude/claude_desktop_config.jsonWindows: %APPDATA%\Claude\claude_desktop_config.json |
mcpServers |
| Claude Code | ~/.claude.json (user scope, and local scope under projects).mcp.json in the project (project scope, often committed) |
mcpServers |
| Cursor | ~/.cursor/mcp.json (all projects).cursor/mcp.json (one project) |
mcpServers |
| VS Code | User: mcp.json in your profile folder (%APPDATA%\Code\User\ on Windows, ~/Library/Application Support/Code/User/ on macOS, ~/.config/Code/User/ on Linux)Workspace: .vscode/mcp.jsonOlder setups: "mcp" in settings.json |
servers |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
mcpServers (remotes use serverUrl) |
| Gemini CLI | ~/.gemini/settings.json (user).gemini/settings.json (project) |
mcpServers (HTTP remotes use httpUrl) |
| Codex | ~/.codex/config.toml |
[mcp_servers.<name>] tables |
Two quick ways to see what's loaded without opening files: claude mcp list
in Claude Code, and the MCP: List Servers command in VS Code.
A project file like .mcp.json, .cursor/mcp.json or .vscode/mcp.json is
easy to commit by accident. Anyone who clones the repo gets it, tokens and all.
Check those first.
What one entry looks like
Every client uses the same two shapes. A local server is a command your machine runs:
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"],
"env": {}
}
A remote server is a URL your client connects to:
"sentry": {
"url": "https://mcp.sentry.dev/mcp",
"headers": {}
}
A local entry runs code on your machine with your user's rights. A remote entry sends your prompts and tool calls to someone else's server. Read each one with that in mind.
Read it by hand: five things to look for
Here is a config with most of the problems in it. We use it again below.
{
"mcpServers": {
"filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/"] },
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_EXAMPLE_NOT_REAL" } },
"context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp@latest"] },
"deploy-helper": { "command": "bash", "args": ["-c", "curl -fsSL https://example.com/install.sh | sh && deploy-mcp"] },
"analytics": { "url": "http://mcp.example-analytics.com/mcp?token=abc123" },
"sentry": { "url": "https://mcp.sentry.dev/mcp" }
}
}
1. Unpinned versions
npx -y some-package with no version, or @latest, runs whatever version npx
resolves when the client starts. That's usually the newest one. A bad release,
or a rug pull,
reaches you without you choosing it.
- Spot it:
npxargs with a bare package name or@latest,uvxwith a bare name, Docker images with no tag or:latest. - Fix it: pin the version you tested:
some-package@1.4.2,uvx some-package@1.4.2, or an image tag or digest.
In the example, server-filesystem, server-github and context7-mcp@latest
are all unpinned.
2. Tokens in env, args or URLs
A token pasted into env sits in plain text in that file. So does one in an
argument or a URL query string, like ?token=abc123 in the example.
- Spot it: values that look like keys (
ghp_,sk-,xoxb-, long random strings) inenv,args,headersorurl. - Fix it: keep the value out of the file. Use your client's variable syntax or an input prompt, and give the token the fewest scopes that work. The steps for each client are in how to keep API keys out of your MCP config.
If the file was ever committed, the token is in your git history. Rotate it.
3. Servers that shell out
Some entries don't start a server package at all. They start a shell.
- Spot it:
bash -c,sh -c,cmd /c,powershell -Command,curl ... | sh, oruvx --from git+https://...pointing at a branch. - Why it matters: the command can change every time the script it downloads
changes, and nobody can grade it.
deploy-helperin the example pipes a remote script intoshon every start. - Fix it: install a named, pinned package instead, or read the script and keep a local copy you control.
Servers whose job is to run shell commands (terminal or "desktop control" servers) are a different case. They do exactly what they say. Keep approval on for every command they run.
4. Plain-HTTP remotes
A remote at http:// (not https://) sends your prompts, tool results and any
token in clear text. analytics in the example does both.
- Spot it:
url,serverUrlorhttpUrlstarting withhttp://, unless it'shttp://localhostor127.0.0.1on your own machine. - Fix it: use the
https://address. If the server doesn't have one, don't use it with a real token.
5. Broad access
- Spot it: a filesystem server given
/or your whole home folder (the example gives it/), Docker with-v /:/hostor--privileged, a database URL for production, a token with every scope. - Fix it: give each server only the folder, database or scopes it needs for the job.
While you're there, check for packages their authors have given up on. In
npm, npm view @modelcontextprotocol/server-github deprecated prints
"Archived and unmaintained; no security guarantees." That's the old GitHub
server in the example. The current one is GitHub's own
GitHub MCP server.
Scan your MCP config: grade every server in one prompt
The hand check tells you how you run each server. It can't tell you whether the server itself has a login, gets updates, or has known CVEs. That's what a grade is for.
Our TrustedMCP MCP server has a
check_config tool for this. (We built it, so weigh that.) Add it, then ask:
Check the MCP servers in my config.
Run with npx, it finds the Claude Desktop, Claude Code, Cursor, VS Code and
Windsurf files above on its own. For Gemini CLI or another client with an
mcpServers JSON file, give it the path. For Codex, ask about each server by
name. The hosted version can't see your files, so paste the config into the
chat.
Here is the real output for the example config, from the live API on 2026-11-12:
Checked 6 MCP servers in 1 config: 3 graded (A 2, D 1), 0 only in the official registry, 3 not found.
### pasted config
- **filesystem**: grade **D**, Filesystem MCP Server. Fix first: No login: keep it local and never expose it on a network. Better graded in its category: Appwrite MCP Server (A), Buildkite MCP Server (A), Sentry MCP Server (A). https://trustedmcp.io/servers/filesystem-mcp-server
- **github**: not found (npm:@modelcontextprotocol/server-github). Review it yourself.
- **context7**: grade **A**, Context7 MCP. Fix first: Login is optional: turn it on. https://trustedmcp.io/servers/context7-mcp
- **deploy-helper**: runs `bash` with a local file or a name we can't match, so it can't be looked up. Review it yourself.
- **analytics**: not found (remote:mcp.example-analytics.com/mcp). Review it yourself.
- **sentry**: grade **A**, Sentry MCP Server. All four checks at full marks. https://trustedmcp.io/servers/sentry-mcp
To ask for a grade: https://trustedmcp.io/submit
Notice what it didn't flag. The grade for Context7 is A, but the config still
runs @latest. The analytics URL shows up without http:// or the token,
because check_config sends only names, package names, image names and URLs
without query strings. Your tokens never leave your machine with the npx
version, and that also means the tool can't warn you about them. That's why you
do both passes.
What to do with each result
A or B. Good starting point. Still fix anything from the hand check: pin it, move tokens out, narrow its access. The "Fix first" line names the one thing that cost it the most points.
C or D. Read the "Fix first" line and the listing. A low grade often comes from something you can work around, like no login on a server you only run over stdio on your own machine. Then decide:
- Keep it, limited. Local only, the narrowest folder or token, approval on for every tool call.
- Swap it. The "better graded" names are in the same category, but they don't always do the same job. Check that one fits before you swap.
- Remove it. If you haven't used it this month, take it out. Every server in the file is something your agent can start.
Not found or "only in the official registry". We have no grade for it. That's not a bad sign on its own, but you have to do the checking:
- Find the repo and see who maintains it, when it last changed and whether issues get answers.
- Run
npm view <package> deprecated(or check PyPI) for an abandoned package. - Ask
registry_lookupabout it. It shows the official MCP Registry entry and any reported security issues. - Ask us to grade it. We add the ones people use.
Local scripts (node /path/to/server.js, python my_server.py) can't be
graded by anyone but you. Read the code, or keep it on a machine with nothing
to lose.
For the full before-you-install checklist, see are MCP servers safe?.
When to scan again
- After you add or update a server.
- When a big MCP CVE is in the news. Our monthly security roundup lists them.
- Once a month anyway. Grades change when servers ship new versions or new CVEs land.
Frequently asked questions
Where is the MCP config file in Claude Code?
User-scope and local-scope servers are in ~/.claude.json. Project-scope
servers are in .mcp.json at the project root, which is often committed to
git. Run claude mcp list to see all of them.
Where is claude_desktop_config.json?
On macOS, ~/Library/Application Support/Claude/claude_desktop_config.json.
On Windows, %APPDATA%\Claude\claude_desktop_config.json. In Claude Desktop,
Settings, Developer, Edit Config opens it.
Is there a tool that scans my MCP config automatically?
Our check_config tool grades every server in it (we built it, so weigh that).
Other tools check different things, like tool descriptions for prompt
injection. MCP security tools compares what each
kind checks and misses. None of them replaces reading the file once yourself.
Does check_config send my tokens anywhere?
Not with the npx version. It reads the file on your machine and sends only server names, package names, image names and server URLs without query strings. Env values, headers, tokens and file paths stay local. With the hosted version you paste the file, so the whole text is sent over HTTPS. We read only those same fields from it.
What is the best MCP server scanner?
It depends on what you want checked, and none of them checks everything.
Scanners like Snyk Agent Scan and Cisco MCP Scanner start your servers and read
their tool descriptions. A grade lookup like our check_config (we built it,
so weigh that) grades each server in your file from public signals without
running it. MCP security tools compares what each
kind checks and misses.
How do I check an MCP server before I add it to my config?
Look it up first: the MCP registry check guide
shows how to confirm it in the official MCP Registry and read any reported
issues. Then read its entry by hand for the five risks above, and ask for its
grade with check_config.
Is an unpinned npx server dangerous?
It's a risk, not a flaw. You run whatever the author published last, without choosing to. Most releases are fine. Pinning means a bad one can't reach you until you decide to update.
What does "not found" mean in the results?
We don't have a grade for that server, or the entry doesn't name a package,
image or URL we can match. Review it yourself, check the official MCP Registry
with registry_lookup, or ask us to grade it.