You've built your MCP (Model Context Protocol) server. It connects to databases, APIs, maybe even cloud infrastructure. Your AI agent can now do real things in the real world.
But have you thought about what happens when something goes wrong?
Here's a practical checklist I use before any MCP deployment goes live. Each item takes 5-15 minutes to verify, and skipping any of them is asking for trouble.
1. ✅ Secrets Are Not in Config Files
The Problem: MCP server configs (claude_desktop_config.json, .cursor/mcp.json) routinely contain API keys, database passwords, and tokens in plaintext.
What to Check:
# Search for common secret patterns in MCP configs
grep -rn 'sk-\|password\|secret\|token\|api_key' ~/.config/claude/ ~/.cursor/
The Fix: Use a secrets manager that provides credentials at runtime. Janee is purpose-built for this — it's an MCP server that provides encrypted secrets to other MCP servers, with scoped access and audit logging.
2. ✅ Each Server Has Minimal Permissions
The Problem: Most MCP servers request broad permissions because it's easier during development. A GitHub MCP server with repo:* scope can delete your production repos.
What to Check: For each MCP server in your config:
- List the scopes/permissions of every credential it uses
- Ask: "Does this server need write access, or just read?"
- Ask: "Does this need access to ALL repos, or just one?"
The Fix: Create dedicated credentials with minimum required scopes. Use separate API keys for read-only vs. read-write operations.
3. ✅ You Have Audit Logs
The Problem: When an AI agent accesses a secret or makes an API call, there's usually no record of it. If something goes wrong, you're flying blind.
What to Check:
- Can you answer: "What secrets were accessed in the last 24 hours?"
- Can you answer: "Which MCP server made this API call?"
The Fix: Enable audit logging at the secrets layer. Janee provides this out of the box — every secret access is logged with timestamp, requesting server, and context.
4. ✅ Credentials Rotate Without Downtime
The Problem: If a credential is compromised, how fast can you rotate it? If it's hardcoded in 5 config files across 3 machines, the answer is "not fast enough."
What to Check:
- Pick any credential your MCP servers use
- Time how long it takes to rotate it everywhere
- If the answer is >5 minutes, you have a problem
The Fix: Centralize credential storage. When secrets live in one place, rotation is a single operation.
5. ✅ Transport Layer Is Encrypted
The Problem: MCP supports both stdio and SSE transports. stdio is local and generally safe. SSE over HTTP (not HTTPS) sends everything — including credentials — in plaintext.
What to Check:
# Look for non-TLS SSE connections
grep -n 'http://' ~/.config/claude/claude_desktop_config.json
The Fix: Always use https:// for SSE transport. For local development, stdio transport avoids the issue entirely.
6. ✅ No Credential Sharing Between Environments
The Problem: Using the same API key in development and production. A bug in your dev MCP server now has production access.
What to Check:
- Compare credentials in dev config vs. prod config
- If any match, that's a finding
The Fix: Separate credentials per environment. Use naming conventions like DEV_GITHUB_TOKEN and PROD_GITHUB_TOKEN to make cross-environment sharing obvious.
7. ✅ Error Messages Don't Leak Secrets
The Problem: MCP servers that include credentials in error messages, stack traces, or logs. One unhandled exception and your API key is in a log file.
What to Check:
# Trigger an intentional error and inspect the output
# Look for credential values in stderr/stdout
The Fix: Sanitize all error output. Never include raw credential values in error messages — use references like GITHUB_TOKEN=sk-...xxxx (last 4 chars only).
8. ✅ You've Tested What Happens When Credentials Expire
The Problem: OAuth tokens expire. API keys get revoked. What does your MCP server do? Crash? Hang? Silently fail?
What to Check:
- Temporarily revoke a credential and see what happens
- Does the MCP server give a clear error?
- Does it retry with a refresh token?
- Does it fail gracefully or take down the whole agent?
The Fix: Implement explicit credential validation on startup and clear error messages for expired/invalid credentials.
9. ✅ Third-Party MCP Servers Are Pinned to Versions
The Problem: Running npx @latest some-mcp-server in production means you're executing whatever code was published most recently — including potential supply chain attacks.
What to Check:
// Bad: unpinned
"command": "npx", "args": ["some-mcp-server"]
// Good: pinned to specific version
"command": "npx", "args": ["some-mcp-server@1.2.3"]
The Fix: Pin every MCP server to a specific version. Review changelogs before upgrading. Consider vendoring critical dependencies.
10. ✅ You Have a Kill Switch
The Problem: An AI agent with MCP access is doing something unexpected. How fast can you cut its access?
What to Check:
- Can you revoke all credentials for a specific MCP server in <60 seconds?
- Can you disable a specific MCP server without restarting the entire agent?
The Fix: Centralized secrets management gives you this for free. Revoke the secret, and the MCP server loses access immediately — no config file editing, no redeployment.
The Meta-Pattern
If you noticed a theme, it's this: most MCP security problems come from decentralized credential management. When secrets are scattered across config files, environment variables, and hardcoded strings, every item on this checklist becomes harder.
The fix isn't any single tool — it's the pattern of centralizing secrets behind an access layer with logging, scoping, and rotation.
That said, if you want a drop-in solution purpose-built for MCP, check out Janee. It handles encrypted storage, scoped access, audit logging, and credential rotation — all exposed as MCP tools that your AI agent can use directly.
Quick Reference
| # | Check | Severity | Time to Fix |
|---|---|---|---|
| 1 | No plaintext secrets in configs | 🔴 Critical | 30 min |
| 2 | Minimal permissions per server | 🔴 Critical | 1 hour |
| 3 | Audit logs enabled | 🟡 High | 15 min |
| 4 | Credential rotation works | 🟡 High | 1 hour |
| 5 | Transport encryption | 🔴 Critical | 10 min |
| 6 | Environment separation | 🟡 High | 30 min |
| 7 | No secret leaks in errors | 🟡 High | 30 min |
| 8 | Graceful credential expiry | 🟢 Medium | 1 hour |
| 9 | Pinned MCP server versions | 🟡 High | 15 min |
| 10 | Kill switch exists | 🟡 High | 30 min |
Start from the top. Fix the criticals first. Everything else follows.
This is part of my MCP Security series. Previously: The Hidden Security Gap in MCP Server Configs, How I'm Using GitHub to Build an Open Source Security Brand, and I Built a Security Scanner for MCP Configs.
Top comments (0)