Guide
How do I secure the MCP servers that coding agents connect to?
Updated
Short answer
Treat MCP servers like dependencies that can take actions. Keep an inventory, allowlist servers by URL or exact launch command, pin and review versions, and give each server a narrow credential. Then check every MCP tool call before it runs. An approved server can still be steered into the wrong action by a poisoned tool description or by content the agent has just read.
An MCP server is either code your developers' agents run or a remote service they hand credentials to. By default nobody vets it. Anthropic's admin docs say anyone running Claude Code can connect any MCP server they choose, and Anthropic doesn't security-audit or manage any MCP server.
You already do this job for packages and extensions. MCP adds one new part: a server you approved can be told to do the wrong thing at runtime.
What the risk actually is#
Most of it comes down to 4 failure modes.
- Poisoned tool descriptions. Invariant Labs described malicious instructions embedded in MCP tool descriptions that users can't see and models can read.
- Rug pulls. The same research shows a malicious server can change a tool description after the client has already approved it. Approval at install tells you nothing about what the server does later.
- Local servers with full reach. The MCP project's own guidance warns that local servers can lead to arbitrary code execution with the MCP client's privileges. On a developer laptop, the client's privileges are the developer's.
- Over-scoped tokens. The same document says poor scope design makes a compromised token more damaging. A broad token on one server can be used for everything that token can reach.
Supply-chain tampering is the same problem one layer up. Malicious versions of the Claude Code extension were live in Cursor's marketplace from about 2:27am to 1:35pm PT, and Cursor says they tried to install a persistent SSH backdoor. The source was approved and the contents were bad. We wrote up what to check.
Controls that work, and what they miss#
| Control | What it stops | What it misses |
|---|---|---|
| Allowlist by URL or launch command | Unapproved servers | A bad call to an approved server |
| Pinned versions, reviewed updates | Silent upgrades, some rug pulls | A server that's malicious from day 1 |
| Scoped, per-user credentials | Blast radius of a stolen token | Misuse inside the token's scope |
| Sandbox and egress limits on local servers | Reach beyond the workspace and approved hosts | Leaks to hosts you allowed |
| Per-call check before execution | Calls that don't fit the task | A determined attacker who controls the code |
Allowlist by what runs, not by name. Claude Code's managed settings let admins control which MCP servers developers can use. But Anthropic's docs say a serverName entry is not a security control, because the user picks the name. Match on the remote server's URL or the local server's exact launch command, and push the policy through the MDM you already run so users can't widen it.
Pin and review like any dependency. If the launch command doesn't pin a version, the next start can pull a release nobody reviewed. Pin versions, review diffs on update, and give each server a named owner.
Scoped credentials. Give each server a token that covers only what the task needs. Make it short-lived where you can, with one identity per developer. Keep shared secrets out of config files that anyone on the machine can read. For the remote OAuth side, see MCP authorization and security.
Sandbox local servers. They run with the developer's privileges, so restrict the files they can read and deny network egress they don't need.
None of these judges an individual call. An allowlisted server with a clean description can still be told to send secrets out or touch production, by a poisoned ticket or a web page the agent has just read.
Checks per call#
Allowlists decide which servers are allowed to exist. They don't decide whether this call, with these arguments, fits what the developer asked for.
Take one MCP tool used with two intents. "Query the staging database for this test" is fine. Pointing the same tool at production customer rows halfway through a CSS task is not.
A useful per-call check looks at the tool name, the arguments, where the data goes and the session's intent. Then it allows, blocks, asks a human or rewrites the call. It also keeps a record of which tool ran, with which arguments, in which session.
A checklist you can use this week#
- Inventory every MCP server in use: URL or command, owner, version and the credential it holds.
- Reject name-only allowlist entries. Enforce by URL and exact launch command.
- Deploy the allowlist as managed settings through MDM.
- Pin versions. Review again whenever a tool description or schema changes.
- Replace shared and long-lived tokens with scoped, per-user ones.
- Sandbox local servers and deny egress they don't need.
- Log tool calls with their arguments in watch-only mode before you enforce anything.
- Add a per-call check for anything that touches production, secrets or the outbound network.
Where Harden fits#
Harden Agentic Integrity Foundation (AIF) runs on the developer laptop, outside the agent, at the agent's pre-execution hook. It checks every command, file edit and push against the session's intent before it runs. Deterministic rules decide when the action itself is the evidence, such as a secret reaching a network call, and a local model checks the session's context for 19 risk categories, including tool and MCP poisoning.
Decisions are made locally, in about 28 ms (P99 about 70 ms). One policy covers every agent. It starts watch-only, so you can see which servers agents actually call before you block anything. Every decision is recorded, and Records can be exported to your SIEM.
AIF is a layer, not a perimeter. It doesn't replace the allowlist, scoped credentials or egress policy. For the laptop side, see securing coding agents on developer laptops. For the wider risk picture, see our MCP security overview.
FAQ
Related questions
Is a serverName allowlist enough in Claude Code?
No. Anthropic's docs say a serverName entry is not a security control, because the user picks the name. Allowlist by the remote server's URL or the local server's exact launch command instead.
What is MCP tool poisoning?
It's malicious instructions hidden in an MCP tool description. The user can't see them, but the model reads them, so the agent can be steered into actions nobody asked for. A malicious server can also change a description after you've approved it.
Are local stdio MCP servers safer than remote ones?
Not by default. The MCP project warns that local servers can mean arbitrary code execution with the client's privileges, which on a laptop are the developer's. Sandbox them, limit their egress and pin their versions.
Can I stop MCP use entirely?
Claude Code's managed settings let admins control which MCP servers developers can connect. Most teams prefer a fixed set of approved servers, enforced by URL or launch command, to a full ban.
How do I see which MCP tools agents are calling?
Build an inventory from the config files on managed machines. For per-call records with arguments, run a pre-execution check in watch-only mode first, then start enforcing once you know what normal looks like.