MCP Server Security: Production Checklist
Most MCP deployments use hardcoded keys with no rotation or scoping. Production checklist: credential rotation, tool-level scoping, audit logging, rate limiting.
Most MCP server deployments in 2026 run with hardcoded API keys, no credential rotation, no tool-level scoping, and no audit trail. This is fine for local development. It is a liability in production where agents run autonomously, handle user data, and make API calls on your behalf 24/7. Here is a production security checklist.
The default MCP security posture is dangerous
A typical MCP config looks like this: API keys in plaintext JSON, every tool exposed to every agent, no rate limiting, no logging of what tools were called with what arguments. An agent compromise (or just a prompt injection) gives full access to every connected service with no way to detect or limit the blast radius.
// BAD: Typical MCP config in production
{
"mcpServers": {
"search": {
"command": "npx",
"args": ["@scavio/mcp-server"],
"env": {
"SCAVIO_API_KEY": "sk-live-abc123..." // Plaintext key
}
// No scoping, no rate limit, no audit
}
}
}Checklist item 1: Credential rotation
Never hardcode API keys in MCP configs. Use environment variable injection from a secrets manager (AWS Secrets Manager, HashiCorp Vault, 1Password CLI). Rotate keys on a schedule -- monthly minimum, weekly preferred. If a key is compromised, you need to rotate without redeploying the entire agent stack.
# Use a secrets manager to inject credentials at runtime
export SCAVIO_API_KEY=$(vault kv get -field=api_key secret/mcp/scavio)
export OPENAI_API_KEY=$(vault kv get -field=api_key secret/mcp/openai)
# Start MCP server with injected credentials
npx @scavio/mcp-serverChecklist item 2: Tool-level scoping
Not every agent needs every tool. A research agent should not have access to a database write tool. A summarization agent should not have access to email sending. Scope tools per agent role.
// GOOD: Scoped MCP config per agent role
{
"mcpServers": {
"search-readonly": {
"command": "npx",
"args": ["@scavio/mcp-server", "--tools=search,serp"],
"env": {
"SCAVIO_API_KEY_REF": "vault://secret/mcp/scavio-readonly"
},
"allowedRoles": ["researcher", "analyst"],
"maxCreditsPerHour": 100
},
"search-full": {
"command": "npx",
"args": ["@scavio/mcp-server", "--tools=search,serp,tiktok,youtube"],
"env": {
"SCAVIO_API_KEY_REF": "vault://secret/mcp/scavio-full"
},
"allowedRoles": ["admin"],
"maxCreditsPerHour": 500
}
}
}Checklist item 3: Audit logging
Every MCP tool invocation should be logged with: timestamp, agent identity, tool name, arguments (redacted if sensitive), response status, and cost. Without audit logs, you cannot detect abuse, debug failures, or track spending.
import json, time, logging
logger = logging.getLogger("mcp_audit")
def audit_tool_call(agent_id: str, tool: str, args: dict, response: dict):
log_entry = {
"timestamp": time.time(),
"agent_id": agent_id,
"tool": tool,
"args": redact_sensitive(args),
"status": response.get("status", "unknown"),
"latency_ms": response.get("latency_ms"),
"credits_used": response.get("credits_used", 0),
}
logger.info(json.dumps(log_entry))
def redact_sensitive(args: dict) -> dict:
sensitive_keys = {"api_key", "password", "token", "secret"}
return {
k: "***REDACTED***" if k in sensitive_keys else v
for k, v in args.items()
}Checklist item 4: Rate limiting per agent
A runaway agent loop can burn through your entire API budget in minutes. Set per-agent, per-hour rate limits. Alert when an agent hits 80% of its limit. Kill the agent process when it hits 100%.
Checklist item 5: Network isolation
MCP servers that connect to external APIs should run in isolated network segments. The agent runtime should only be able to reach the MCP server, not the external APIs directly. This prevents a compromised agent from bypassing MCP controls by calling APIs directly.
The full checklist
- No plaintext credentials in config files -- use vault/secrets manager
- Rotate API keys monthly minimum
- Scope tools per agent role -- principle of least privilege
- Log every tool invocation with agent identity and arguments
- Set per-agent rate limits with alerting at 80% threshold
- Network-isolate MCP servers from direct external API access
- Validate tool arguments before execution (input sanitization)
- Implement circuit breakers for failing external services
- Review audit logs weekly for anomalous patterns
- Test credential rotation without downtime before going live
Production MCP security is not optional in 2026. Agents are running autonomously, handling real data, and spending real money. Treat MCP servers like any other production service: secure credentials, minimal permissions, full observability.