The governing assumption

Design as though the AI will eventually be manipulated. Filtering helps; it is not a foundation. The defence that holds is tool scope — if a fully compromised agent still cannot exfiltrate, delete or spend, the attack has nowhere to go.

MCP servers sit between an AI model and your systems, which makes them a security boundary. These are the design decisions that determine whether that boundary holds.

The attack surface

AttackHow it worksPrimary defence
Prompt injectionInstructions hidden in retrieved contentNarrow tool scope; approval gates
Privilege escalationAgent accessing data beyond the user's rightsPer-user permission mapping
Data exfiltrationManipulating the agent into sending data outNo unrestricted outbound tools
Parameter injectionMalicious values passed to a toolStrict input validation
Resource exhaustionAgent looping, generating volumeRate limits and spend caps
Confused deputyAgent using its own broad rights on requestAct as the user, not as the service

Prompt injection in practice

Your agent reads content authored outside your control — supplier emails, customer tickets, uploaded documents, web pages. Any of it can contain text designed to redirect the model.

The mistake is treating this as a filtering problem. Filters catch obvious attempts and miss creative ones. The reliable defence is architectural: if your tools cannot send data anywhere, cannot delete, and cannot spend without confirmation, then a successfully manipulated agent achieves nothing worth the attacker's effort.

Layered mitigations, in order of reliability:

  1. Tool scope — the agent simply cannot perform harmful operations. Most reliable.
  2. Approval gates — consequential actions require a human, who sees what is proposed.
  3. Structural separation — retrieved content clearly delimited from instructions in the prompt.
  4. Content filtering — detecting obvious injection patterns. Useful, insufficient alone.
  5. Output checking — verifying responses do not contain data that should not leave.

Tool design rules

  • One tool, one operation. "Get order by ID", not "query orders".
  • Never expose arbitrary execution — no raw SQL, no generic HTTP request tool, no shell access. These recreate the problem you built the server to solve.
  • Validate every parameter against a schema. Type, format, range. An order ID must look like one.
  • Constrain result size. A tool returning ten thousand records is an exfiltration vector and a cost problem.
  • Return only necessary fields. If the assistant needs status, do not return the full customer record.
  • Make tool descriptions precise. Vague descriptions cause wrong tool selection, which looks like unreliability.

Every convenience you add to a tool is capability an attacker inherits. The most secure tool is the narrowest one that still does the job.

Permission mapping

The single most important control, and the one most often skipped in early implementations:

  • Resolve the requesting user's identity, not the service account's.
  • Apply their permissions — the agent sees exactly what that person could see directly.
  • Never use a shared privileged credential for all requests.
  • Fail closed. If identity cannot be established, deny rather than defaulting to broad access.
  • Re-check per call. Permissions change; a long session should not carry stale rights.

The test that validates your permission model: have two users with genuinely different access ask the same question through the assistant. If they get the same answer, your model is not working — the agent is using its own rights rather than theirs, which is the confused-deputy problem.

Approval gates, calibrated properly

Action typeReversible?Gate
Read a recordN/AAutomatic
Search or summariseN/AAutomatic
Create a draftYesAutomatic
Update a recordUsuallyConfirm or log prominently
Send a message externallyNoAlways confirm
Issue payment or refundNoAlways confirm
Delete dataNoAlways confirm

Gate by reversibility and blast radius rather than by a simple read/write split. An internal draft is a write and carries no risk; an outbound email is a write and cannot be recalled.

Operational controls

  • Rate limits per user and per session — the primary defence against a looping agent.
  • Spend caps on anything with a per-call cost.
  • Timeouts so a stuck tool call does not hold resources indefinitely.
  • Instant revocation — a documented way to disable access immediately, tested before you need it.
  • Alerting on anomalies — unusual volume, repeated failures, access patterns outside the norm.

Audit logging that is actually useful

  • Requesting user identity, tool name, parameters, result summary, timestamp, outcome.
  • Retained long enough to investigate an incident discovered weeks later.
  • Stored where the agent cannot modify them.
  • Reviewed on a sample basis, with automated alerts on patterns.

Logging you never read provides evidence after an incident but prevents nothing. Periodic review is what turns it into a control.

Testing before deployment

  1. Injection testing — documents containing manipulation attempts in the corpus.
  2. Permission testing — different users, same question, verified different results.
  3. Parameter fuzzing — malformed and boundary inputs to every tool.
  4. Rate limit verification — confirm limits actually engage.
  5. Revocation drill — disable access and confirm it takes effect immediately.

Building an MCP server that has to pass security review? Tell us what systems it will front. See our MCP server service, secure enterprise data access, and guardrails to demand.

Frequently asked questions

No. It can be contained. Filtering and instruction separation reduce success rates but cannot be relied on absolutely, which is why the primary defence is tool scope — designing so that even a fully manipulated agent cannot do serious damage.
Yes, but with confirmation for anything consequential. The distinction that matters is reversibility: creating a draft is low risk, sending an email or issuing a refund is not. Gate by blast radius rather than by read-versus-write.
Log identity, tool name, parameters, result summary and timestamp for every call — then actually review a sample periodically. An audit trail nobody reads catches nothing. Automated alerts on unusual patterns are more useful than volume.