← All docs

MCP security guide

Inventory MCP servers, scope individual tools and credentials, and test policy before allowing agent access.

A trusted server can still receive the wrong call for the wrong reason. Review the capability, not just the name.
An MCP call is checked by server and tool identity before policy allows, asks, or denies it.

A trusted server can still receive the wrong call for the wrong reason. Review the capability, not just the name.

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:

  1. The agent proposes an MCP call.
  2. agentjail identifies the server and tool.
  3. Local policy returns allow, ask, or deny.
  4. 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:

  1. Record its source, version, and owner.
  2. List every tool it exposes.
  3. Identify the credential and permissions behind each sensitive tool.
  4. Allow read-only tools first.
  5. Put external writes behind ask.
  6. Block destructive and administrative tools by default.
  7. Restrict filesystem and network access around the server process.
  8. Test one allowed call and one denied call.
  9. Keep decision logs long enough to investigate an incident.
  10. 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