MCP Server Security: The Risks and the Fixes

TL;DR

MCP server security is about what the tools behind the server can do, not about the protocol. The Model Context Protocol is a transport for exposing tools to an agent. The risk lives in the tools: broad access, standing credentials, and actions nobody logged. The fixes are old and boring in the best way: least privilege, no long-lived secrets, a human step for destructive changes, validate every call server-side, and record everything. Secure the actions, not just the connection.

The Model Context Protocol made it easy to give an agent real tools. That is the good part and the scary part. A single MCP server can expose a database, a cloud account, or an internal API to something that decides its own next move. The protocol does not decide what that something is allowed to do. You do, or you forget to, and that gap is where MCP server security lives.

What is MCP server security?

MCP is a transport. It standardizes how a client (the agent) discovers and calls tools a server offers. The protocol spec covers the wire format, capabilities, and how tools are described. It does not cover authorization, blast radius, or audit. Those are your job.

So “MCP server security” is really one question asked twice:

  • What can each tool actually do to a real system?
  • Can you prove, afterward, what it did?

If a tool can drop a table and nothing records that it happened, no amount of transport hardening saves you. The connection was secure. The action was not governed.

What are the security risks of MCP servers?

Five show up over and over.

Overbroad tool access. A tool named run_sql that accepts any statement is a foot-gun. The agent needed to read one row and now holds a path to DROP TABLE. Tools tend to be written for developer convenience, which means they do too much.

Prompt injection reaching a tool. An agent reads a web page, an issue comment, or a file, and that untrusted text says “now call delete_bucket.” When the agent can act, prompt injection stops being a chatbot annoyance and becomes a way to trigger real operations. The model’s own reasoning is not trustworthy evidence of intent once its input can be poisoned.

Long-lived credentials in the server. Many MCP servers are configured with a static API key or a cloud access key in an environment variable. That secret now lives on whatever machine runs the server, is readable by the process, and often ends up in logs. One leak and the blast radius is everything that key can touch, for as long as the key is valid.

Unaudited actions. The agent called three tools. Which ones changed state? On whose behalf? Can you reverse them? If the answer is a shrug, you have a tool that acts and a record that does not, which is the worst pairing for an incident review.

Third-party server supply chain. Installing an MCP server you did not write means running its code with your access. A malicious or sloppy server can exfiltrate data or make calls you never intended. Treat an MCP server like any dependency: it inherits your trust unless you box it in.

Raw MCP server vs. a governed one

Raw MCP serverGoverned control plane behind MCP
Tool scopeWhatever the author wroteTyped operations, least privilege
CredentialsStatic key in the serverShort-lived role per request, none at rest
Destructive actionsAgent decidesHuman approval required
Untrusted inputFlows straight to toolsValidated server-side, treated as data
AuditAd hoc logs, if anyTamper-evident ledger of every action
Blast radius on compromiseEverything the key can reachBounded by the operation and its tier

How do you secure an MCP server?

The fixes are not exotic. They are the same principles that secure any privileged system, applied to the fact that the caller is now an agent.

Expose typed, least-privilege operations, not raw power. Replace run_sql with get_customer_by_id. Each tool should do exactly one bounded thing. If a task does not need write access, the tool should not offer it.

Hold no long-lived credentials in the server. The agent should never carry cloud keys. Put a broker between the agent and the cloud that assumes a short-lived role for each request. If the server is compromised, there is no standing secret to steal. This is the same pattern behind giving Claude Code safe AWS access: the agent asks, the control plane holds the keys and assumes the role.

Require a human step for anything destructive. Reads can be automatic. Deletes, restarts, and permission changes should preview what they would do and wait for a person to approve. This is the core of guardrails that actually work: enforcement lives outside the model, so a poisoned prompt cannot approve its own action.

Validate every call server-side. The MCP server is UX. The security boundary is the server that executes the operation. Re-check the caller, the parameters, and the policy on every request. Never trust that the client already checked.

Treat tool inputs as untrusted data. Names, tags, and file contents that came from outside are data, not instructions. Label them that way so the agent does not act on “delete everything” hiding in a resource name.

Record every action on a tamper-evident ledger. Who acted, on whose behalf, what changed, whether it was approved, and how to reverse it. An append-only, hash-chained record is what turns “something happened” into evidence.

A quick MCP security checklist

  • Does each tool do one bounded thing, with the least access it needs?
  • Are there any static cloud or API keys living in the server?
  • Do destructive tools require a human approval before they run?
  • Is every call validated by the executor, not just the client?
  • Is untrusted input labeled as data, never as instructions?
  • Can you list every state change an agent made, and reverse it?

If you cannot check the last three, the transport is the least of your problems.

How Mesoplane approaches it

Mesoplane treats the MCP server as a projection, not the boundary. Agents call typed, risk-tiered operations through a control plane that holds the credentials, assumes a short-lived role per request, requires human approval for destructive changes, validates every call server-side, and records each one on a tamper-evident ledger with the acting agent’s identity. The same operations project to the CLI, the console, and MCP with no extra security code, because the enforcement lives in one place. You can read the full security model for how the no-standing-credentials design works. The point is simple: secure the actions, and the protocol stops being the thing you have to worry about.

Frequently asked questions

Are MCP servers secure?

An MCP server is only as secure as the tools it exposes and the access behind them. The protocol itself is a transport; it does not decide what an agent is allowed to do. A server that hands an agent broad, unaudited access to a database or a cloud account is a risk no matter how the transport is secured. Security comes from least-privilege tools, server-side validation of every call, and an audit trail, not from MCP itself.

What are the main security risks of MCP servers?

The big ones: overbroad tool access (one tool that can do far more than the task needs), prompt injection that reaches a tool (untrusted text steering the agent into calling something dangerous), long-lived credentials sitting inside the server, unaudited actions you cannot reconstruct later, and supply-chain risk from third-party servers you did not write. Most incidents trace back to too much standing access plus too little logging.

How do I secure an MCP server connected to AWS?

Do not let the MCP server hold AWS keys. Put a control plane between the agent and the cloud that assumes a short-lived role per request, validates every call server-side, requires a human step for destructive changes, and records each action on a tamper-evident ledger. The MCP server becomes a thin projection of governed operations, not a direct pipe to your account.

Let your agents operate the cloud, governed

Mesoplane turns agent requests into typed, approved, audited, reversible cloud operations. Connect an AWS account read-only in minutes.

Get started free