An MCP server is code with access to tools, data, and often your network. The friendly name in a config file does not make it safe. If a server can read a repository, create a release, query production, or send a message, an agent may be able to do the same thing through that server.
MCP security starts with a plain question: what can this server do from the account and machine where it runs?
Why MCP servers need their own security review
There are three common failure modes.
The server is malicious. It was installed from an untrusted package or copied from a config snippet without reviewing the code.
The server is legitimate but over-scoped. A GitHub server used to read issues also has permission to delete repositories. A database server used for schema inspection can write to production.
The agent is manipulated. Prompt injection in a README, issue, web page, or tool result convinces the agent to call a valid tool for the wrong reason.
The third case is easy to miss.
Start with an inventory
You cannot secure MCP servers you do not know exist.
agentjail mcp scan
The inventory checks supported Claude Code, Codex, and Cursor configurations, plus package and container sources. Use it to answer:
- Which servers are configured?
- Where did each server come from?
- Which agents can call it?
- Does the server run locally or connect to a hosted service?
- What account, token, filesystem path, or database can it reach?
Run the inventory again when configuration changes. MCP setup tends to spread through copied JSON, dotfiles, and team onboarding scripts.
Allow servers deliberately
agentjail uses an explicit MCP allowlist. During installation it seeds the list from servers that are already configured, so review that initial trust instead of assuming it is a permanent verdict.
agentjail mcp list
agentjail mcp allow github
agentjail mcp block my-payment-bot
The same configuration can live in ~/.agentjail/policy.yaml:
mcp:
allowed:
- github
- context7
blocked:
- "*payment*"
- "*billing*"
The blocklist wins when a name matches both lists.
Restrict tools inside an allowed server
Server-level trust is usually too coarse. A server can contain ten read-only tools and one destructive tool. Blocking the entire server frustrates people; allowing every tool grants more power than the job needs.
Set a verdict at the tool level:
agentjail mcp tool allow github list_repos
agentjail mcp tool ask github create_repo
agentjail mcp tool block github delete_repo
Or describe it in policy:
mcp:
allowed:
- github
servers:
github:
blocked_tools:
- delete_repo
- transfer_repo
ask_tools:
- create_repo
A good default is simple:
- Allow read-only discovery tools.
- Ask before writes with a meaningful external effect.
- Block destructive, administrative, billing, and credential operations unless there is a specific reason to expose them.
Limit the credential behind the server
Policy around the tool call is one layer. The server’s own credential is another.
If an MCP server only needs to read issues, give it a token that can read issues. Do not give it an organization-owner token and rely on the agent to use it politely. The same rule applies to database users, cloud roles, Slack apps, and deployment credentials.
Prefer:
- short-lived credentials over standing tokens;
- project or repository scope over organization scope;
- read-only access when writes are not required;
- staging accounts for testing;
- separate identities for agents and people.
If a policy layer fails, the credential should still limit the damage.
Account for prompt injection
Prompt injection is not limited to chat messages. An agent reads untrusted text from repositories, issues, package documentation, web pages, and MCP tool results. Any of that text can contain instructions.
Do not use the model’s judgment as the only authorization check. Put a deterministic decision between the model and the tool:
- The agent proposes an MCP call.
- agentjail identifies the server and tool.
- Local policy returns
allow,ask, ordeny. - Only an allowed or explicitly approved call proceeds.
This does not make prompt injection disappear. It limits which actions an injected instruction can turn into reality.
Review network access
A local MCP server can still make outbound requests. Document the hosts it needs, then compare that list with what the process can actually reach.
For agents launched through the transparent tunnel, agentjail can enforce an outbound hostname allowlist:
network:
allowed_hosts:
- api.github.com
- "*.your-company.example"
Network controls should complement tool policy. Tool policy understands the requested action. Network policy limits where the resulting process can talk.
MCP security checklist
Before approving a server for a team:
- Record its source, version, and owner.
- List every tool it exposes.
- Identify the credential and permissions behind each sensitive tool.
- Allow read-only tools first.
- Put external writes behind
ask. - Block destructive and administrative tools by default.
- Restrict filesystem and network access around the server process.
- Test one allowed call and one denied call.
- Keep decision logs long enough to investigate an incident.
- Repeat the review when the server or its permissions change.
The goal is not to make MCP unpleasant to use. It is to stop one convenient integration from quietly becoming a universal admin interface.
Next steps
- Default MCP policy: shipped rules, inventory behavior, and configuration examples.
- Policy model: how multiple rules resolve to one decision.