@ferrierepete/mcpshield
v0.2.2
Published
Security scanner for MCP (Model Context Protocol) servers — detect supply chain risks, permission overreach, and misconfigurations
Maintainers
Readme
🔒 MCPShield
Security scanner for MCP (Model Context Protocol) servers. Detect supply chain risks, permission overreach, and misconfigurations before they compromise your system.
Why?
MCP (Model Context Protocol) is the standard way AI tools like Claude Desktop, VS Code, and Cursor connect to external services. Every MCP server you install can execute arbitrary code on your machine.
Recent attacks include:
- Mass-forking & republishing of MCP servers with malicious payloads (HN, March 2026)
- Typosquatting — packages mimicking official
@modelcontextprotocolservers - Rug pulls — legitimate packages updated to include malicious code
- Data exfiltration — servers secretly sending your data to external endpoints
MCPShield scans your MCP configuration and flags these risks before they become incidents.
Install
npm install -g @ferrierepete/mcpshieldQuick Start
# Auto-detect and scan your MCP config
npx @ferrierepete/mcpshield scan
# Scan a specific config file
npx @ferrierepete/mcpshield scan --config ~/.config/claude/config.json
# Output as JSON (for CI/CD)
npx @ferrierepete/mcpshield scan --format json
# Output as Markdown
npx @ferrierepete/mcpshield scan --format markdown
# Output as SARIF (for GitHub Security tab)
npx @ferrierepete/mcpshield scan --format sarif
# Enable remote registry checks (npm/PyPI)
npx @ferrierepete/mcpshield scan --registry
# Filter by severity
npx @ferrierepete/mcpshield scan --severity high
# Ignore specific findings
npx @ferrierepete/mcpshield scan --ignore MCP-001 MCP-003
# Quiet mode (CI-friendly one-liner output)
npx @ferrierepete/mcpshield scan --quiet
# Filter by severity (critical | high | medium | low | info)
npx @ferrierepete/mcpshield scan -s high
# Ignore findings by ID or title (partial matching supported)
npx @ferrierepete/mcpshield scan --ignore MCP-001 Typosquat
# Filter out low-confidence findings (heuristic, no API key needed)
# Warns if all findings are filtered to zero
npx @ferrierepete/mcpshield scan --min-confidence 0.7
# AI-powered false positive reduction (BYOK — bring your own key)
npx @ferrierepete/mcpshield scan --ai --ai-provider openai
npx @ferrierepete/mcpshield scan --ai --ai-provider anthropic
npx @ferrierepete/mcpshield scan --ai --ai-provider gemini
# Use a custom OpenAI-compatible endpoint (Groq, Together, Ollama, etc.)
npx @ferrierepete/mcpshield scan --ai --ai-provider openai --ai-base-url http://localhost:11434/v1
# Auto-fix common issues
npx @ferrierepete/mcpshield fix
npx @ferrierepete/mcpshield fix --dry-run
# Watch config for changes and re-scan
npx @ferrierepete/mcpshield watch
# List discovered config files
npx @ferrierepete/mcpshield list
# Show OWASP MCP Top 10 reference
npx @ferrierepete/mcpshield owaspWhat It Detects
| Category | Checks |
|----------|--------|
| Supply Chain | Unpinned versions, unverified packages, known risky packages, typosquats |
| Registry | Package existence on npm/PyPI, recently published packages, single-version packages, missing source repos (with --registry) |
| Permissions | Broad filesystem access, sensitive working directories, overly permissive runtime flags |
| Secrets | Hardcoded API keys, tokens in plaintext config |
| Configuration | Missing commands, shell injection patterns, dangerous runtime flags, eval/exec patterns |
| Network | Binding to 0.0.0.0, suspicious URLs (pastebin, webhook.site, etc.), IP-based server URLs |
| Docker | --privileged flag, sensitive volume mounts, Docker socket exposure, unpinned image tags, exposed ports |
| HTTP/SSE Transport | Insecure HTTP connections, missing authentication headers on remote servers |
| Threats | Typosquatting, obfuscated values, data exfiltration indicators |
Commands
mcpshield scan
Scan MCP server configurations for security issues.
| Flag | Description |
|------|-------------|
| -c, --config <path> | Path to MCP config file |
| -f, --format <fmt> | Output format: pretty, json, markdown, sarif |
| -r, --registry | Enable remote npm/PyPI registry checks |
| -s, --severity <level> | Minimum severity: critical, high, medium, low, info |
| -i, --ignore <ids...> | Finding IDs or titles to ignore (substring matching — --ignore typo matches "Potential Typosquat") |
| -q, --quiet | One-line summary output (ideal for CI scripts) |
| --min-confidence <n> | Minimum confidence threshold (0.0–1.0) to display findings |
| --ai | Enable AI-based false positive reduction (requires API key) |
| --ai-provider <name> | AI provider: openai, anthropic, gemini |
| --ai-model <model> | Override the default AI model |
| --ai-base-url <url> | Custom base URL for OpenAI-compatible endpoints |
| --no-spinner | Disable progress spinner |
mcpshield fix
Auto-fix common security issues in your MCP config.
| Flag | Description |
|------|-------------|
| -c, --config <path> | Path to MCP config file |
| --dry-run | Preview fixes without writing changes |
Supported auto-fixes:
- Pin package versions — appends
@latestto unpinned packages - Replace hardcoded secrets — substitutes with
${VAR_NAME}references - Bind to localhost — replaces
0.0.0.0with127.0.0.1 - Upgrade to HTTPS — replaces
http://withhttps://for remote URLs - Remove empty env vars — cleans up empty or wildcard environment variables
mcpshield watch
Watch your MCP config file and re-scan automatically on every change.
| Flag | Description |
|------|-------------|
| -c, --config <path> | Path to MCP config file |
| -f, --format <fmt> | Output format: pretty, json, markdown, sarif |
mcpshield list
List all discovered MCP configuration files on your system.
mcpshield owasp
Display the OWASP MCP Top 10 security framework reference.
Security Score
MCPShield generates a 0-100 security score:
- 80-100 ✅ Good — minor improvements possible
- 60-79 ⚠️ Warning — meaningful risks to address
- 0-59 🔴 Critical — immediate action required
OWASP MCP Top 10
MCPShield maps findings to the OWASP MCP Top 10 framework:
| ID | Category | |----|----------| | MCP-01 | Malicious Server Distribution | | MCP-02 | Tool Poisoning | | MCP-03 | Rug Pull Attacks | | MCP-04 | Cross-Origin Resource Sharing | | MCP-05 | Prompt Injection via Tools | | MCP-06 | Unauthorized Tool Access | | MCP-07 | Data Exfiltration | | MCP-08 | Identity Spoofing | | MCP-09 | Token/Secret Exposure | | MCP-10 | Dependency Confusion |
Example Output
🔒 MCPShield Security Report
──────────────────────────────────────────────────
Config: /home/user/.config/claude/config.json
Date: 2026-04-02 22:15:00
Security Score: 42/100
Findings: 2 critical 3 high 1 medium
📦 filesystem-dangerous [25/100]
Command: npx
🔴 Broad Filesystem Access [MCP-001]
Server has access to path "/". This grants read/write access to sensitive system directories.
→ Fix: Restrict filesystem access to only the specific directories this server needs.
Refs: MCP-06: Unauthorized Tool Access, MCP-07: Data Exfiltration
🟠 Sensitive Credentials in Config [MCP-002]
Found 1 sensitive environment variable(s): AWS_SECRET_ACCESS_KEY
→ Fix: Use a secrets manager instead of hardcoding credentials.
📦 github-safe [100/100]
✅ No security issues foundCI/CD Integration
# GitHub Actions — JSON output
- name: MCP Security Scan
run: npx @ferrierepete/mcpshield scan --format json
# Exits with code 2 for critical, 1 for high findings
# GitHub Actions — SARIF for Security tab
- name: MCP Security Scan (SARIF)
run: npx @ferrierepete/mcpshield scan --format sarif > results.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarifConfiguration
.mcpshieldrc
Create a .mcpshieldrc, .mcpshieldrc.json, or .mcpshield.json file in your project root or home directory to set defaults:
{
"severityThreshold": "medium",
"ignore": ["MCP-001"],
"format": "pretty",
"registry": false,
"trustedPackages": ["@myorg/custom-mcp-server"],
"riskyPackages": ["some-known-bad-package"],
"ai": true,
"aiProvider": "openai",
"aiModel": "gpt-4o-mini",
"minConfidence": 0.6
}MCPShield searches for this file in the current directory first, then the home directory.
Customizing Package Lists
Trusted and risky package lists are stored as JSON files in src/data/:
trusted-packages.json— packages verified as legitimaterisky-packages.json— packages known to be malicious or suspicioussuspicious-patterns.json— URL patterns and typosquat regexes
AI False Positive Reduction
MCPShield uses a two-layer system to reduce false positives:
Layer 1: Heuristic Confidence Scoring (always on, no API key)
Every finding gets a confidence score (0.0–1.0) based on contextual rules:
- Trusted packages flagged as unpinned → lower confidence
- Localhost HTTP connections → lower confidence
- Env vars using
${VAR}references → lower confidence - Private IP addresses → lower confidence
--privilegedDocker flag → higher confidence- Known risky packages / typosquats → higher confidence
Use --min-confidence 0.7 to filter out low-confidence findings.
Layer 2: AI Evaluation (opt-in, BYOK)
Pass --ai to send findings to an LLM for contextual evaluation. Each finding receives a verdict:
- confirmed — real security risk
- likely-false-positive — probably safe in this context
- needs-review — human should verify
Supported providers:
| Provider | Flag | Env Var(s) | Default Model |
|----------|------|-----------|---------------|
| OpenAI | --ai-provider openai | OPENAI_API_KEY or MCPSHIELD_OPENAI_API_KEY | gpt-4o-mini |
| Anthropic | --ai-provider anthropic | ANTHROPIC_API_KEY or MCPSHIELD_ANTHROPIC_API_KEY | claude-sonnet-4-20250514 |
| Google Gemini | --ai-provider gemini | GEMINI_API_KEY, GOOGLE_API_KEY, or MCPSHIELD_GEMINI_API_KEY | gemini-2.0-flash |
| OpenAI-compatible | --ai-provider openai --ai-base-url <url> | Same as OpenAI | — |
Works with Groq, Together AI, Ollama, and any OpenAI-compatible endpoint via --ai-base-url.
Additional env vars:
MCPSHIELD_AI_MODEL— override the default model for any providerMCPSHIELD_AI_BASE_URL— set a custom OpenAI-compatible endpointMCPSHIELD_AI_PROVIDER— set the default provider without--ai-providerflag
Security note: MCPShield never sends your secrets to the AI. Only env var keys (not values) are included in the prompt.
Plugin System
Extend MCPShield with custom scanners via the plugin API:
import { pluginRegistry, definePlugin, createFinding } from '@ferrierepete/mcpshield';
pluginRegistry.register(definePlugin({
name: 'my-org-policy',
description: 'Enforce internal security policies',
scan: (serverName, config) => {
const findings = [];
// Your custom checks here
if (!config.env?.AUDIT_LOG) {
findings.push(createFinding({
title: 'Missing Audit Log',
description: 'Internal policy requires AUDIT_LOG env var.',
severity: 'medium',
category: 'configuration',
serverName,
remediation: 'Add AUDIT_LOG=true to the server environment.',
}));
}
return findings;
},
}));Plugins support both sync and async scanners, and errors in plugins are isolated — a crashing plugin won't affect the rest of the scan.
Programmatic API
MCPShield can be used as a library in your own Node.js tooling:
import {
scanAllServers,
scanAllServersWithRegistry,
loadConfig,
autoDetectConfig,
} from '@ferrierepete/mcpshield';
// Load a config file
const config = loadConfig('/path/to/mcp.json');
// Run a local scan
const result = scanAllServers(config.mcpServers, '/path/to/mcp.json');
console.log(`Score: ${result.summary.score}/100`);
console.log(`Critical: ${result.summary.critical}`);
// Run with remote registry verification
const fullResult = await scanAllServersWithRegistry(config.mcpServers, '/path/to/mcp.json');
// Access per-server findings
for (const server of fullResult.servers) {
console.log(`${server.name}: ${server.findings.length} findings`);
for (const finding of server.findings) {
console.log(` [${finding.severity}] ${finding.title}`);
console.log(` Fix: ${finding.remediation}`);
}
}Key Exported Types
import type {
ScanResult, // Top-level result from scanAllServers
ServerScanResult, // Per-server findings and score
Finding, // Individual security finding
Severity, // 'critical' | 'high' | 'medium' | 'low' | 'info'
FindingCategory, // 'supply-chain' | 'permissions' | 'configuration' | ...
MCPConfig, // Parsed MCP config file shape
MCPServerConfig, // Individual server config
} from '@ferrierepete/mcpshield';Security Hardening
MCPShield includes several built-in protections to prevent misuse:
- Path traversal prevention — all config paths (whether from
--config,MCP_CONFIG_PATH, or auto-detection) are validated viaresolveSafeConfigPath(). Only paths within your current working directory or home directory are allowed. Attempts to load files like/etc/passwdor/proc/self/environare rejected with a clear error - Config backup before writes — the
fixcommand creates a.bakbackup of your config file before applying any changes - Secret key sanitization — the
fixcommand sanitizes env var key names containing shell metacharacters (e.g.$(cmd),`cmd`,;rm -rf) by deleting the dangerous key and replacing it with a safe alphanumeric name - AI response size limits — AI provider responses are capped at 1 MB to prevent memory exhaustion from unbounded responses
- Registry fail-closed — when npm/PyPI registry checks fail (network errors, HTTP 500, rate limits), packages are treated as unverified rather than silently passing
- Secret values never sent to AI — only env var keys (not values) are included in AI evaluation prompts
Config Locations
MCPShield auto-discovers configs from all major MCP clients:
| Client | Scope | Path |
|--------|-------|------|
| Claude Desktop | macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop | Linux | ~/.config/Claude/claude_desktop_config.json |
| Claude Desktop | Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Claude Code | User/Local | ~/.claude.json |
| Claude Code | Project | .mcp.json |
| Claude Code | Local | .claude/settings.local.json |
| VS Code | Workspace | .vscode/mcp.json |
| Cursor | Global | ~/.cursor/mcp.json |
| Cursor | Project | .cursor/mcp.json |
| Windsurf | Global | ~/.codeium/windsurf/mcp_config.json |
| Continue | Global | ~/.continue/config.json |
| Zed | Global | ~/.config/zed/settings.json |
| Custom | — | MCP_CONFIG_PATH environment variable |
MCPShield handles the different config formats automatically — mcpServers (object), servers (VS Code), context_servers (Zed), and array-based mcpServers (Continue).
License
MIT © Peter Ferriere
