MCP Security Best Practices: What You Can Actually Do

All these risks might sound overwhelming — and they are. But that doesn’t mean you’re defenseless. The best defense is knowing how these attacks work and setting guardrails before bad actors get creative.
Here’s a field-tested list of security practices for anyone building with the Model Context Protocol:
1. Lock Down Your MCP Server
Too many devs launch MCP-compatible tools with no authentication. That’s a gift to attackers.
Minimum standard: Add API key authentication, OAuth2, or mutual TLS (mTLS). If your server handles any sensitive action — like reading emails, accessing databases, or sending messages — you need to verify who’s calling.
Treat every incoming request as hostile until proven otherwise.
2. Sanitize All Inputs (Even from the LLM)
Don’t trust the AI. Don’t trust the human. Don’t trust the internet.
Any input that triggers code execution, shell commands, or remote calls needs to be validated, escaped, or rejected. This includes:
- File paths
- Shell commands
- API parameters
- User prompts
Use shlex.quote()
in Python. Validate with JSON schemas. Restrict dangerous operations to a known safe subset.
3. Reduce Tool Scope
Don’t give your tools more power than they need.
A tool that just sends emails shouldn’t also be able to access the file system or issue shell commands. Use environment variables, scoped credentials, or permission wrappers to enforce this.
Principle of Least Privilege isn’t just for humans. Apply it to your tools too.
4. Don’t Hardcode Tool Descriptions
Avoid baking tool descriptions into your tool logic. If a malicious agent or LLM manipulates the system prompt or output, your tool may behave in unexpected ways.
Instead, have your server serve its own description dynamically from a secure endpoint — and monitor it regularly.
5. Log Everything — Especially Tool Use
Every call to your MCP server should be logged:
- Timestamp
- Caller identity (if known)
- Request body
- Result or error code
Store logs securely and set alerts for weird patterns. One rogue call to “deleteAll” could be your only warning.
6. Throttle Sensitive Tools
If your tool can do something destructive (delete files, modify user data, send mass emails), enforce rate limits.
Throttle by IP, token, or user session. Better yet, add manual approval or double-confirmation workflows for risky operations.
7. Don’t Assume Tool Responses Are Safe
A malicious tool can respond with whatever it wants. If your LLM blindly incorporates that response into its own output or logic, attackers can steer the conversation or even inject hidden instructions.
Always check: is this response safe to display? Should it be filtered? Does it need validation?
8. Use System Messages to Limit LLM Behavior
If your agent uses an LLM to call tools, use system messages or guardrails to restrict what the model is allowed to do.
Example system message:
“You may only call tools that begin with 'safe-'. Never call tools with 'debug-' or 'shell-' in the name.”
This isn’t bulletproof — but it helps contain the blast radius.
9. Regularly Pen-Test Your Agent and Tools
Use red teams. Simulate injections. Fuzz your endpoints. Treat your agent as if it were a real employee — one that can be tricked, manipulated, or socially engineered.
If you don’t test your defenses, an attacker eventually will.
10. Build a Kill Switch
If something goes wrong, can you shut it down?
Add an emergency stop endpoint. Limit timeouts. Monitor behavior. Make it easy to revoke tokens and cut off bad agents mid-execution.
When you’re building with autonomy, you need an eject button.