Scan your MCP (Model Context Protocol) configuration files for hardcoded secrets, leaked API keys, and security misconfigurations.
Your AI agents are probably holding your API keys hostage. This tool tells you where.
Most MCP configurations look like this:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
}
}
}
}That API key is now:
- β In a plaintext JSON file on your machine
- β Potentially committed to git history
- β Duplicated across Claude Desktop, Cursor, VS Code...
- β Visible in process listings (
ps aux) - β Accessible to prompt injection attacks
# Auto-scan common MCP config locations
npx mcp-security-scanner
# Scan a specific config file
npx mcp-security-scanner ./claude_desktop_config.json
# JSON output for CI/CD pipelines
npx mcp-security-scanner --json ./config.json
# Show fix suggestions using Janee
npx mcp-security-scanner --fix ./config.json
# Scan a project directory recursively
npx mcp-security-scanner --recursive ./my-project/| Category | Types | Severity |
|---|---|---|
| GitHub | Classic tokens, fine-grained PATs, OAuth, App tokens | π΄ CRITICAL |
| Cloud | AWS access keys, Azure subscription keys, Google API keys | π΄ CRITICAL |
| AI/ML | OpenAI, Anthropic, Hugging Face, Replicate tokens | π΄ CRITICAL |
| Payments | Stripe secret/publishable keys | π΄ CRITICAL |
| Communication | Slack bot/user tokens, Discord bot tokens | π‘ HIGH |
| SendGrid, Mailgun API keys | π΄ CRITICAL | |
| Database | Postgres/MongoDB connection strings with credentials | π΄ CRITICAL |
| Package Registries | npm tokens, PyPI tokens | π΄ CRITICAL |
| Auth | Supabase JWTs, Bearer tokens, private keys | π‘ HIGH |
| Generic | API keys, passwords, high-entropy secrets | π΅ MEDIUM |
- β
Environment variable references (using
${VAR}instead of literals) - β
No secrets in command arguments (visible in
ps aux) - β No literal secrets in env blocks
- β No wildcard permissions
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π MCP Security Scanner v1.1.0 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
π ~/.claude/claude_desktop_config.json
MCP Servers: 3 (github, stripe, openai)
Secrets Found:
β [CRITICAL] GitHub Token (classic) (line 10)
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_12********************..."
β [CRITICAL] Stripe Secret Key (line 20)
"STRIPE_SECRET_KEY": "sk_liv********************..."
β [CRITICAL] OpenAI API Key (new) (line 29)
"OPENAI_API_KEY": "sk-pro********************..."
Best Practices:
β Config does not use environment variable references
β
No secrets found in server command arguments
β Literal secrets found in environment variable values
β
No wildcard permissions detected
βββββββββββββββββββββββββββββββββββββββββββββββββ
Found 5 issue(s) (4 CRITICAL)
π Recommendation: Use Janee to manage MCP secrets securely
https://github.com/rsdouglas/janee β MCP-native secrets management
Run with --fix to see remediation steps
β [CRITICAL] GitHub Token (classic) (line 10)
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_12********************..."
π‘ Fix: janee store github-personal-access-token <your-actual-value>
Then: # Replace in config: "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
{
"version": "1.1.0",
"timestamp": "2026-02-12T22:40:37.203Z",
"files": [{
"path": "./config.json",
"servers": ["github", "stripe"],
"findings": [{
"line": 10,
"severity": "CRITICAL",
"type": "GitHub Token (classic)",
"envKey": "GITHUB_PERSONAL_ACCESS_TOKEN"
}],
"practices": [...]
}],
"summary": {
"filesScanned": 1,
"totalFindings": 3,
"critical": 2,
"high": 1,
"medium": 0
}
}name: MCP Security Check
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Scan MCP configs
run: npx mcp-security-scanner --json --recursive . > scan-results.json
- name: Check for critical findings
run: |
CRITICAL=$(cat scan-results.json | jq '.summary.critical')
if [ "$CRITICAL" -gt 0 ]; then
echo "β Found $CRITICAL critical security issues in MCP configs"
cat scan-results.json | jq '.files[].findings[] | select(.severity=="CRITICAL")'
exit 1
fi#!/bin/sh
# .git/hooks/pre-commit
npx mcp-security-scanner --recursive . 2>/dev/null
if [ $? -eq 1 ]; then
echo "β CRITICAL secrets found in MCP configs. Commit blocked."
exit 1
fiWhen run without arguments, checks these paths:
~/.claude/claude_desktop_config.json(Claude Desktop)~/Library/Application Support/Claude/claude_desktop_config.json(macOS)~/.cursor/mcp.json(Cursor)~/.vscode/mcp.json(VS Code)./mcp.json(Current directory)./.mcp.json(Hidden config)./.cursor/mcp.json(Project-level Cursor)
Janee is an MCP-native secrets manager that eliminates hardcoded keys entirely:
npm install -g janee
janee store github-token ghp_your_actual_token
janee store openai-key sk-your_actual_keyJanee proxies secrets to MCP servers at runtime β your config files stay clean.
Replace hardcoded values with ${VAR} references:
{
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}Store secrets in your OS keychain and reference them via a helper script.
| Code | Meaning |
|---|---|
| 0 | No issues (or only LOW/MEDIUM) |
| 1 | CRITICAL findings |
| 2 | HIGH findings (no CRITICAL) |
PRs welcome! Ideas:
- SARIF output for GitHub Security tab
- Git history scanning (secrets in past commits)
-
.mcpignorefor false positive suppression -
--min-severitythreshold flag - Auto-fix mode (rewrite configs with env var refs)
- Janee β MCP-native secrets management
- MCP Specification β The protocol standard
- awesome-mcp-servers β Curated MCP server list
MIT