Academy · MCP security

MCP server security. One server, every agent that calls it.

An MCP server exposes tools to agents, and each tool calls another system with the server’s own credential. That makes the server an identity in its own right, and its reach is inherited by every agent allowed to call it.

.vscode/mcp.json
{
  "servers": {
    "crm": {
      "command": "npx",
      "args": ["-y", "crm-mcp-server"],
      "env": { "CRM_TOKEN": "••••••" }
    }
  }
}
KEY TAKEAWAYS
  • An MCP server is a non-human identity. Its tools call other systems with its own key, token or service account.
  • Every agent that calls a server inherits that server’s reach, and its log lines usually cannot be attributed to any single caller.
  • Local and remote servers fail differently: local puts a long-lived token on a machine, remote moves the credential to an operator whose breach reaches every customer.
  • The first hardening step is a list of servers in use. The config files, repositories and CI workflows that start them are where to look.

Published Last reviewed

MCP SERVERS

The server is the identity. The agents are just callers.

MCP server security is about one question: what can this server reach, and who can make it reach. The protocol gives an agent a clean way to call tools. It does not change the fact that each tool calls another system with a credential, and that credential is where the access actually lives.

This is why a server with ten careful agents in front of it is not safer than its own token. For the protocol risks themselves, step by step, read the MCP security checklist. This page is about the server as an identity.

THE SHORT VERSION

Every agent that calls a server inherits everything that server’s credential can reach.

RISKS

Five risks specific to the server.

Not protocol flaws. These are properties of how servers are configured and shared in real environments.

01
The server is an identity, and usually a single one

Every tool the server exposes calls another system with the server’s own key, token or service account. Ten agents calling one server all act with that identity, so the server’s reach is the reach of all of them, and its log lines cannot be attributed to any of them.

02
Tokens sit in plain text in the config

A local server is configured in a file with an env block, and the token goes in that block. The file lives on a developer machine next to the agent, which means anything that can read the machine can read the token, including the agent itself.

03
Scopes are granted for the widest tool

A server with six tools usually holds one credential wide enough for all six. The read-only summary tool and the write-anything tool share it, so using the harmless tool and using the dangerous one are the same permission.

04
Tool descriptions are part of the agent’s input

An agent decides which tool to call from the descriptions the server returns. A server you do not control therefore gets to influence the agent’s behaviour, which makes server provenance an access question rather than a preference.

05
Nobody removes a server after the experiment

A server added to try something out keeps its entry in the config and its credential in the env block. It is the most common way an MCP server becomes a shadow agent with standing access.

LOCAL VS REMOTE

Local and remote fail differently.

The common question is which one is safer. The useful question is which failure you would rather be able to detect.

Local serverRemote server
How it runsAs a process on the user machine, usually over stdio.Over HTTP, operated by somebody else.
Where credentials liveIn the config file, often plain text in an env block.With the operator, reached through OAuth or an API key.
What to check firstWhich machine holds the file, and what else can read it.Which scopes the grant carries, and who the operator is.
What a compromise reachesEverything readable on that machine, plus the token’s own reach.Every customer of that server, through the operator.
Who can revoke itThe developer, by editing the file.You, by revoking the grant, if you know it exists.
PRACTICE

How to harden one. Four steps.

In this order. Step one is the one most teams skip, and it is the one that makes the rest possible.

01List the servers before the risks

Search for MCP configuration on the machines and in the repositories that matter: the config files agents read, and workflow files that start a server in CI.

02Give each server its own identity

One credential per server, and where the client supports it one per agent and server pair, so rotating one does not break the rest and the log says who called.

03Scope to the narrowest tool that must work

Decide the scope from the tools you actually use, not the tools the server offers. A server you only read from does not need a credential that can write.

04Get the token out of the file

Use the client’s secret storage or a short-lived credential where the server supports it. Where it does not, record that as an accepted risk with an owner rather than leaving it undocumented.

EXAMPLE

What it looks like in Elmoz

One server in the middle, every agent that calls it and the data behind its token.

Security GraphFocus: Cursor agentAll assetsIdentitiesData stores
ATTACK PATH1 API call · 9 seconds
Cursor agentClaude Opus · staging task!Unrelated fileHolds the tokenStagingAssigned environment!Railway CLI tokenCreated for domainsCustom domainsIntended use!All environmentsToken scope: root1GraphQL APIvolumeDelete · no confirm3Findings3 issuesProduction volumeRailway volumeReservationsCustomer data!Volume backupsSame volume
FAQ

Questions, answered.

Short answers on securing Model Context Protocol servers.

Is an MCP server a non-human identity?

In practice yes. It calls other systems with credentials such as API keys, OAuth tokens or service accounts, and those credentials define what it can reach. Treating it as an identity rather than as a tool is what makes the access question answerable.

Which is safer, a local or a remote MCP server?

Neither by default, they fail differently. A local server puts a long-lived token on a developer machine, so the question is what else can read that machine. A remote server moves the credential to an operator, so the question becomes what a breach at that operator would reach across all of their customers.

How do I audit which MCP servers are in use?

Start with the configuration files the clients read, then the repositories and CI workflows that start servers, then the model provider and API keys that appear with new client identifiers. The first list will be incomplete, which is itself the finding.

See what your agents can reach. Before someone else does.

Book a demo and we walk through the access paths in an environment like yours.