The MCP Security Model: Trust Boundaries You Actually Have
AI Agents

The MCP Security Model: Trust Boundaries You Actually Have

MCP standardises connection, not trust. Here are the real boundaries in an MCP deployment and the attacks that cross them, with practical mitigations.

Adding an MCP server to an agent feels like installing a plugin. It is closer to granting a third party the ability to write instructions directly into your model's context, with your credentials attached.

That is not an argument against MCP. It is an argument for being precise about where the trust boundaries sit, because the protocol deliberately does not decide that for you. It standardises how components connect; deciding what they are allowed to do remains entirely yours.

Where the boundaries actually are

There are four parties and three boundaries worth naming.

Between the user and the host application: the user trusts the host to act on their behalf and not to exceed what they asked for. Between the host and the model: the host must treat model output as a proposal, never as an authorised instruction. Between the host and each server: the host trusts the server with whatever credentials and data it passes, and the server trusts the host to be a legitimate caller.

The boundary people forget is the one inside the context window. Content returned by a server arrives in the same channel as your system prompt and the user's request, and the model has no reliable way to tell them apart. Everything a server returns is, functionally, untrusted input with the privileges of trusted input.

The confused deputy, restated for MCP

An agent holds credentials for several systems at once. It reads an issue from a tracker, then writes to a repository, then posts to a chat channel. Anyone who can influence the content of that issue can attempt to influence what the agent does next with the other two.

This is the classic confused deputy, and MCP makes it easier to reach because tool access is now easy to add. An agent with one server is a narrow target; an agent with nine servers is a router between nine systems, and the attacker only needs to control content in one of them.

The mitigation is not to detect malicious text, because that is a losing game. It is to make the damage bounded regardless: the write tools should be scoped narrowly, the destructive ones should require confirmation, and the credentials should be the minimum the task needs. Prompt injection and the confused deputy problem covers the general shape.

Server-side injection is the specific risk

Two variants matter. The first is a compromised or malicious server returning content crafted to redirect the agent — instructions embedded in what looks like a search result, or a tool description that quietly tells the model to exfiltrate whatever it reads.

The second is more common and less discussed: an honest server faithfully returning attacker-controlled data. Your issue tracker server is not malicious, but the issue body was written by whoever opened the issue. Your email server is trustworthy and the email is not.

Practical mitigations. Wrap external content in explicit delimiters and label its provenance in the prompt, so the model at least has the information that this text is data. Never let tool-returned text be treated as a system-level instruction. And treat tool descriptions as configuration to be reviewed on change, not as a field a server can silently mutate between sessions — a description that changes after you approved it is a supply chain event.

Credential scope is where the real control is

Every other mitigation is probabilistic. Scoping is not: an agent cannot delete a production table with a read-only connection, no matter what the model was persuaded to attempt.

Give each server its own credential rather than sharing one. A database server gets a role limited to the schemas it needs; a repository server gets a token scoped to the specific repositories in play; an internal API server gets a service account with a narrow permission set. When something goes wrong, the blast radius is one server's scope rather than everything.

Prefer per-user identity over per-deployment secrets on any shared server. A remote server holding one team-wide token cannot enforce per-user permissions, so every user effectively has the union of everyone's access, and your audit log cannot tell you who did what. MCP transport options covers how identity works over each transport.

Rotate, and make rotation cheap enough that you actually do it. A long-lived token pasted into a config file on several laptops is the most likely thing to leak in this entire architecture.

Local servers inherit everything

A stdio server runs as a subprocess of the host, with the permissions of the user who launched it. On a developer machine that means the working tree, the SSH keys, the cloud credentials in the home directory and the ability to run arbitrary commands.

Installing a community MCP server is therefore equivalent to running an unaudited program with your full user privileges, on an ongoing basis. That is a normal thing developers do, but it is worth doing consciously: pin versions rather than tracking a moving tag, read what a server does before installing it, and prefer ones whose source you can inspect.

Where a server does not need broad access, take it away. Run it in a container with a mounted working directory and no credential volume, or under a restricted user account. Agent sandboxing covers the isolation options and what each actually contains.

Confirmation gates, placed where they matter

Asking a human to approve everything trains them to approve everything. The gate has to be rare enough that it still carries information when it appears.

Gate on irreversibility rather than on risk in the abstract. Sending an external message, deleting data, spending money, pushing to a shared branch, changing permissions — these deserve a prompt. Reads, searches and writes to a scratch workspace do not.

Make the prompt show the actual arguments, not the tool name. "Approve send_email?" tells the user nothing; showing the recipient, the subject and the body lets them catch the case where the agent was redirected. Human-in-the-loop design covers keeping the gate meaningful.

What to do before you add the next server

Write down what data it can read, what it can change, and whose credentials it uses. If any of those answers is broader than the task needs, narrow it first. Give it a dedicated credential. Pin its version. Decide which of its tools are irreversible and gate those. Log every call with arguments so an incident is reconstructable.

Then assume, permanently, that anything it returns may be attacker-controlled, and check that your system is still acceptable under that assumption. If the answer depends on the model not being fooled, the design is not finished. MCP server design covers the other side of the boundary, for servers you build yourself.

Common questions

Does MCP introduce new security problems?

Not new categories, but it lowers the cost of adding tool access, so agents end up bridging more systems at once. An agent connected to nine servers is a router between nine systems, and an attacker only needs to influence content in one.

How do I defend against a server returning malicious content?

Assume you cannot detect it. Bound the damage instead: dedicated narrowly scoped credentials per server, confirmation gates on irreversible actions, and never treating tool-returned text as a system-level instruction.

Is a local stdio server safer than a remote one?

It avoids network exposure and authentication complexity, but it runs with your full user permissions — working tree, SSH keys, cloud credentials. Pin versions, inspect what you install, and containerise servers that do not need that access.

Similar articles

Agent Audit Logging: What to Record and What to Redact
AI Agents
AI Agents·9 min read

Agent Audit Logging: What to Record and What to Redact

When an agent does something surprising, the log is the only account of what happened. What a usable agent audit record contains, and what it must not.

Read
Agent File System Access: Designing the Blast Radius
AI Agents
AI Agents·8 min read

Agent File System Access: Designing the Blast Radius

The filesystem is an agent's most consequential tool surface. Path containment, read and write asymmetry, and why files are an injection vector.

Read
Agent Network Access Control: Egress Is the Real Risk
AI Agents
AI Agents·9 min read

Agent Network Access Control: Egress Is the Real Risk

An agent with a shell and open network egress can exfiltrate anything it can read. How to scope outbound access without breaking the toolchain.

Read