Part of the AI coding agent security checklist
Securing MCP servers for coding agents
An MCP server is code you run, or an account you hand over, and the agent decides when to call it. Know what each one can reach before you approve it.
Checked against Claude Code's documentation, the MCP specification's security guidance, the research under Sources, and ranwhat's source. Published .
What an MCP server can reach
Claude Code does not sandbox an MCP server for you. Anthropic reviews connectors against its listing criteria before they appear in its directory, but does not security-audit or manage any MCP server, and says so on its security page.
The permission prompt for a tool call is a check on each call, not on the code behind it. A server you approved once keeps the access you gave it. For the same reasoning applied to the credentials themselves, see token scopes for AI agents.
The risks that are documented
Read what is configured
Servers come from several places, and reviewing a repository's .mcp.json does not show them all. Plugins can add servers, and so can claude.ai connectors.
| Scope | Loads in | Shared | Stored in |
|---|---|---|---|
| Local (default) | That project only | No | ~/.claude.json, under the project's path |
| Project | That project only | Yes, through version control | .mcp.json in the project root |
| User | All your projects | No | ~/.claude.json |
When one name is defined twice, the higher scope wins: local, then project, then user, then plugin servers, then claude.ai connectors, and field values are not merged. Local scope is ~/.claude.json, not .claude/settings.local.json.
claude mcp list # every server and its status claude mcp get <name> # one server's definition claude mcp remove <name> --scope user claude mcp reset-project-choices # forget your .mcp.json approvals /mcp # inside a session: status, sign-out, disable
Approve less, allow less
Project servers from a clone
In an interactive session, Claude Code asks before it uses a server from a project's .mcp.json. Since v2.1.196, an approval committed to the repository's own .claude/settings.json (enableAllProjectMcpServers or enabledMcpjsonServers) is ignored until you trust the folder, so a clone cannot approve its own servers. Approvals in your ~/.claude/settings.json, in managed settings and in --settings still apply, so keep enableAllProjectMcpServers out of your user settings unless you mean it.
Rules for mcp__server__tool
MCP permission rules use the server name as you configured it, then optionally a tool name.
{
"permissions": {
"allow": [
"mcp__github__get_*"
],
"deny": [
"mcp__github__delete_repository",
"mcp__filesystem"
]
}
}Permissions cover what the agent does with MCP tools. They do not change what the server process can do on your machine. For that, the controls are the token it holds and where it runs.
Limit what a server holds, and who can add one
For an organisation
By default anyone can connect any server. Managed settings change that.
See what this machine has configured
ranwhat reach reads the configuration your agents keep and lists the MCP servers and credential files they can reach. It only reads, and it writes no settings.
ranwhat reach ~/code/app checks one project, and --json prints it as data. To see what agents already did, including MCP calls, run uvx ranwhat check.
A short routine
claude mcp list # do you recognise every server? uvx ranwhat reach # inline secrets, unpinned packages, auto-approved .mcp.json /permissions # inside Claude Code: which mcp__ rules apply
Remove what you do not use, move keys to ${VAR}, pin the packages, and replace any whole-server allow with named tools. For the record of what the agent actually called, read the Claude Code audit log guide. For the rest of the controls, the AI coding agent security checklist, and the other guides are listed here.
Sources
- Connect Claude Code to tools via MCPscopes, commands, .mcp.json expansion, project approvals, headersHelper, OAuth storage
- Configure permissionsmcp__server__tool rules, globs, parentheses skipped
- Claude Code securityMCP security, trust dialog, no audit of servers
- Control MCP server access for your organizationmanaged-mcp.json, allow and deny lists, serverName caveat
- Settings referencethe enable, disable, allow and deny MCP keys and where they can be set
- MCP security best practiceslocal server compromise, startup commands, scope minimization
- Invariant Labs: tool poisoning attackshidden descriptions, shadowing, rug pulls, the Cursor demonstration
- Mitiga: stealing MCP tokens in Claude Codethe trust and re-pointed server chain, the disclosure
- ranwhat/reach.pywhat reach reads and reports
- ranwhat READMEthe reach command, its files and its limits