Field notes
MCP server security and auth
An MCP server is a remote code execution surface with good manners. Treat it that way.
A remote MCP server is an API whose primary caller is a language model acting on instructions it partly read from untrusted content. That is the threat model in one sentence, and it should change how you build.
Ordinary API security still applies. What follows is the part that is specific to serving agents.
Identity: three parties, not two
A normal API has a caller and a server. An MCP server has a client application, an end user, and a model in the middle deciding what to invoke. Your token has to carry enough to answer all three questions: which integration is calling, on whose behalf, and with what permitted surface.
- Per-client tokens. One per integration, revocable independently. Never one key for everyone.
- User context inside the token. For multi-user products, the token binds to an end user so row-level permissions still apply downstream.
- Short lifetimes with refresh. Long-lived bearer tokens in agent configuration files leak. Assume it and limit the window.
- Tool allowlist on the token. A read-only integration must be structurally unable to reach a write tool.
Never let the model choose its own permissions
I have reviewed servers with a tool that takes a role parameter, or a boolean called confirm, and treats it as authorization. The model will set that parameter based on context it does not fully control. That is not a permission system, it is a suggestion box.
Authorization decisions are made server-side from the token, every time, with no input from the arguments. This is the same principle as the runtime-permission argument in prompt injection is not a prompt problem, applied at the protocol boundary.
Three tiers for tools
- Read. Runs unattended. Still rate limited, still scoped, still logged, and still filtered by the caller's data permissions.
- Write, reversible. Requires validation, an idempotency key, and a bounded blast radius. Creating a draft, adding a note, updating a status.
- Irreversible. Sending money, sending email to customers, deleting records, changing access. These require a human approval step or a one-time signed grant issued for that exact payload.
Tier three is where teams get uncomfortable, because a human gate feels like it defeats the automation. It does not. The agent still does all the preparation and reasoning. A person spends two seconds approving a summary. That trade has never once been the wrong call in my experience.
Untrusted content is the main attack path
The realistic attack is not someone hitting your server directly. It is a document, ticket, email, or web page containing instructions, which your tool faithfully returns, and which the model then treats as guidance.
- Label retrieved content as data. Fence it clearly and state in the tool description that the content is untrusted and must not be followed as instruction.
- Strip or neutralize instruction-shaped patterns in returned text where the format allows it.
- Separate contexts. The agent that reads untrusted documents should not be the agent that holds write credentials. Pass structured findings between them, not raw text.
- Validate outputs against a schema before any write. A write tool that only accepts a narrow shape cannot be talked into arbitrary behavior.
The payload was one line in the footer of a PDF. The agent had permission to email, so it emailed.
Rate limits and cost as security controls
Agents fail by repetition. A malformed loop can hit a tool thousands of times in a minute, and if that tool is expensive, that is a financial denial of service.
- Per-token and per-tool rate limits with proper 429 responses.
- Daily call ceilings per token, alerting before the hard stop.
- Duplicate-call detection. Identical arguments repeated in a short window is a bug signature worth rejecting outright.
- Spend attribution per token so you can find the expensive caller in minutes, per the metrics in observability.
Audit logging that would survive a review
If a customer asks what your agent did to their data on a Tuesday in March, you need an answer that does not involve guessing.
Log caller identity, token scope, tool, normalized arguments, outcome, timestamp, and the agent run ID. Keep it append-only. Keep write and irreversible calls far longer than read calls. Redact payload content but never the fact of the call. That distinction is what makes the log both useful and safe to retain.
Deployment hygiene
- Server-side secrets only. Never let a tool return a credential, and never accept one as an argument.
- Egress restrictions on the server, so a compromised dependency cannot quietly exfiltrate.
- Separate staging server with its own tokens and its own data. Agents exploring your staging environment against production data is a preventable category of incident.
- A documented revocation path. When a token leaks, the fix should be one command, not an investigation.
Ship checklist
- Per-client, short-lived, scoped tokens with tool allowlists.
- Server-side authorization only, never from arguments.
- Read, reversible write, and irreversible tiers enforced in code.
- Untrusted content fenced, separated, and schema-validated.
- Rate limits, daily caps, duplicate-call rejection.
- Append-only audit log with run correlation.
- Egress limits, staging isolation, one-command revocation.
The design side of the server, tool shape and testing, is in shipping a production MCP server. If you want your surface reviewed by someone who has broken a few, that is included in the AI production readiness audit.
Frequently asked
How do you authenticate an MCP server?
Issue short-lived, scoped tokens per client and per user, validate them on every call, and attach a tool allowlist to each token. For multi-user products, exchange the end user's identity for a downstream credential rather than sharing one service key.
Should an MCP server use one shared API key?
No, not for anything multi-user. A shared key means every caller has every permission and your audit log cannot attribute actions. Per-client tokens with narrow scopes are the minimum bar.
How do you handle destructive tools safely?
Put irreversible actions behind an explicit approval step or a one-time signed token issued for that specific action and payload. The agent should be able to request the action and unable to complete it alone.
What should an MCP audit log contain?
Caller identity, token scope, tool name, normalized arguments, outcome, timestamp, and a request ID that ties back to the agent run. Keep write and irreversible calls on a longer retention than read calls.
Want this shipped in your stack?
The $1,000 AI audit gets you a ranked action plan in 48 hours.
90-minute live review of your workflows, agents, retrieval, permissions, evals, costs, and observability. Fee credits toward the build.

Written by
Alex Cinovoj, TechTide AI
Founder and CTO of TechTide AI, a Columbus, Ohio AI-automation agency, and co-host of the Automation Vibes podcast. 13 years of mixed IT across support, systems, cloud, architecture, and engineering, with the last 2 years on AI implementation. Lovable Champion and community leader, and has completed Anthropic Academy courses in Agent Engineering, Claude Code, MCP, and Context Engineering.