Secure an MCP server by deciding four things up front: which tokens it accepts, which tools each user can call, which actions need a human to confirm, and what it is allowed to reach on the network. The Model Context Protocol specification and its security best practices page cover each of these. This post turns them into a checklist.
It applies to people who build servers, people who run clients, and people who approve a new connector for their team.
1. Accept only tokens meant for you
The MCP authorization specification says servers must validate that access tokens were issued specifically for them, and must reject tokens that do not name them as the audience. The security best practices go further and call "token passthrough" an anti-pattern that is explicitly forbidden: a server accepts a token from a client and forwards it downstream without checking who it was issued to.
Why it matters: passthrough lets someone with a stolen token use your server as a proxy, and it breaks the audit trail, because downstream logs show the wrong caller. Checklist:
- Validate the audience claim on every request.
- Never forward a client's token to another API. Obtain a separate token for the downstream call.
- Log which client and which user made each call.
2. Give each user the smallest tool set
The spec says servers must implement proper access controls and validate all tool inputs. OWASP's excessive agency entry names the typical failures: extra functions the task does not need, permissions broader than the task needs, and too much autonomy.
- Start from read-only tools and turn others on one at a time.
- Split tools by function. A tool that reads documents should not also delete them.
- Use per-user credentials for downstream systems, not one privileged shared identity.
- Remove tools you tried and dropped.
3. Keep a human in the loop for sensitive actions
The tools section of the spec says there should always be a human in the loop with the ability to deny tool invocations. Clients are advised to show tool inputs to the user before calling the server, to avoid malicious or accidental data exfiltration, and to prompt for confirmation on sensitive operations.
Decide which of your tools are sensitive, and mark them. Anything that sends data out, changes access, deletes, or spends money belongs on that list.
Also note what the spec says about tool descriptions: clients should consider tool annotations untrusted unless they come from trusted servers. A description is text written by whoever runs the server, and it is read by a model. Treat it like input.
4. Treat local servers as code you are running
The best practices describe local server compromise: a client configuration can contain a startup command, and that command runs with the client's privileges. The spec says a client that supports one-click local server setup must show the exact command, without truncation, and require explicit approval.
- Read the full command before you approve a local server.
- Prefer a server that runs in a sandbox with limited file and network access.
- For servers meant to run locally, prefer the stdio transport, or require an authorization token on an HTTP transport.
- Prefer a hosted, authenticated server from the vendor over a community package that claims to wrap it.
5. Stop the client from being steered to internal addresses
During OAuth discovery, a client fetches URLs that a malicious server controls. The spec's SSRF section warns about links to private ranges, localhost and cloud metadata addresses, and about redirects and DNS rebinding.
- Require HTTPS for OAuth URLs outside local development.
- Block private, loopback and link-local ranges, using a maintained library rather than your own parser. The spec warns that custom parsers miss encoding tricks.
- Do not follow redirects blindly, and consider an egress proxy for server-side clients.
6. Confirm consent for proxies
If your MCP server proxies a third-party API with a static client ID, the spec requires per-client consent before forwarding to the third party, exact redirect URI matching, and a state parameter validated at the callback. Skipping these is how a consent cookie from a past login gets reused for an attacker's request.
How does Safeguard handle this on its own server?
Safeguard publishes a hosted MCP server at mcp.safeguard.sh. The docs say it connects with OAuth, shows the app name and the host that receives the authorization code before you approve, and starts a new workspace with a small read-only tool set that an administrator expands per tool. The docs also state that Safeguard publishes no npm package or local bridge for it, and that any package claiming to be the Safeguard MCP server should be treated as untrusted.
What to do
- List every MCP server your team uses and mark each as hosted or local.
- For each, write down the tool list and mark sensitive tools.
- Switch the sensitive tools to confirm-before-run in your client.
- Review local server commands for network calls, sudo and access to home directory files.
- If you build servers, add audience validation and per-client consent before anything else.
- Log tool calls with user, client and arguments, and review them after incidents.
Quick check
Is it fine to pass the user's token through to the API behind my server?
No. The MCP specification forbids token passthrough. Accept only tokens issued for your server, and get a separate credential for downstream calls.
Are tool descriptions trustworthy?
Treat them as untrusted unless they come from a server you trust. They are text read by a model and can steer it.
Sources
- MCP specification: Security Best Practices
- MCP specification: Authorization
- MCP specification: Tools
- OWASP Gen AI Security Project, LLM06:2025 Excessive Agency
- Safeguard docs: Claude Integration
Last reviewed: 18 October 2026.