Skip to main content

MCPGuard

PyPI version Python versions License: MIT CI

Security scanner and runtime protection for MCP servers.

MCP is becoming the TCP/IP of AI agents. MCPGuard makes sure it doesn't become the next Log4j.

MCPGuard scans your MCP server configurations for the vulnerabilities in the OWASP MCP Top 10 and provides runtime middleware to enforce security policies on every tool call. It works without a running server — pure static analysis of your config files.


Install

pip install mcpguard

Quick Start

# Scan your Claude Desktop or Cursor MCP config (auto-detected)
mcpguard scan

# Scan a specific config
mcpguard scan --config ./claude_desktop_config.json

# Get a JSON report
mcpguard scan --format json --output report.json

Programmatic usage:

from mcpshield import scan

result = scan()
print(f"Score: {result.score}/100  ({result.rating})")
for finding in result.sorted_findings():
    print(f"[{finding.severity.value}] {finding.rule_id}: {finding.title}")

What It Detects

MCPGuard covers all 10 categories of the OWASP MCP Top 10:

Rule Severity OWASP Description
MCPS-001 CRITICAL MCP01 Hardcoded API keys and secrets in env vars
MCPS-002 HIGH MCP03 Filesystem server with access to / or ~/.ssh
MCPS-003 HIGH MCP08 npx -y with unverified or unpinned packages
MCPS-004 CRITICAL MCP04 Shell invocation enabling command injection
MCPS-005 HIGH MCP05 HTTP/SSE server without authentication or TLS
MCPS-006 HIGH MCP03 Wildcard tool permissions (files:*, admin:*)
MCPS-007 MEDIUM MCP02 Tool descriptions with injection keywords or hidden Unicode
MCPS-008 MEDIUM MCP10 URL parameters without domain allowlisting (SSRF)
MCPS-009 LOW MCP09 Missing audit logging configuration
MCPS-010 HIGH MCP06 Shared session memory without user isolation
MCPS-011 MEDIUM MCP05 stdio server running without sandboxing
MCPS-012 CRITICAL MCP08 Known CVE — mcp-remote, MCP Inspector, filesystem

CLI

# Scan auto-detected config
mcpguard scan

# Scan specific file
mcpguard scan --config ./mcp-config.json

# Output formats
mcpguard scan --format json --output report.json
mcpguard scan --format sarif --output report.sarif   # GitHub Security tab
mcpguard scan --format html --output report.html     # Shareable HTML

# Fail CI on critical/high findings
mcpguard scan --fail-on critical
mcpguard scan --fail-on high

# Skip specific rules
mcpguard scan --skip-rules MCPS-009,MCPS-011

# Check a package against the vulnerability database
mcpguard check-package mcp-remote
mcpguard check-package mcp-remote@0.1.7

# Generate a starter policy file
mcpguard init-policy --output policy.yaml

# Validate an existing policy
mcpguard validate-policy policy.yaml

Runtime Guard

Protect your MCP server's tool handlers at runtime with policy enforcement:

from mcpshield.runtime import MCPGuard, Policy

# Load security policy
policy = Policy.from_yaml("policy.yaml")

# Create guard
guard = MCPGuard(policy=policy)

# Protect tool handlers
@guard.protect
async def handle_tool_call(tool_name: str, arguments: dict) -> dict:
    # Blocked tools raise PolicyViolationError before reaching here
    # Path and domain restrictions are enforced automatically
    # Rate limits are checked per-tool
    ...

Policy File

# policy.yaml
version: "1.0"
rules:
  blocked_tools:
    - "execute_command"
    - "run_shell"

  tool_restrictions:
    filesystem_read:
      allowed_paths:
        - "/data/**"
        - "/public/**"
      blocked_paths:
        - "~/.ssh/**"
        - "~/.aws/**"
    http_request:
      allowed_domains:
        - "api.github.com"
      blocked_domains:
        - "169.254.169.254"  # AWS metadata
        - "localhost"

  rate_limits:
    default: 100/minute
    per_tool:
      database_query: 20/minute

  approval_required:
    - "delete_file"
    - "send_email"

  audit:
    enabled: true
    log_file: "mcpguard_audit.jsonl"
    log_level: "all"

CI/CD Integration

Add to .github/workflows/security.yml:

name: MCP Security Scan

on: [push, pull_request]

jobs:
  mcpguard:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install mcpguard
      - name: Scan MCP config
        run: mcpguard scan --config ./claude_desktop_config.json --fail-on high
      - name: Generate SARIF report
        run: mcpguard scan --config ./claude_desktop_config.json --format sarif --output mcpguard.sarif
      - name: Upload to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: mcpguard.sarif

Writing Custom Rules

Extend BaseRule to add your own checks:

from mcpshield.scanner.rules.base import BaseRule
from mcpshield.scanner.finding import Finding, ServerConfig
from mcpshield.utils.severity import Severity

class MyCustomRule(BaseRule):
    rule_id = "CUSTOM-001"
    title = "My Security Check"
    owasp_mapping = "MCP01"

    def check(self, server: ServerConfig) -> list[Finding]:
        findings = []
        if "dangerous_pattern" in str(server.raw):
            findings.append(Finding(
                rule_id=self.rule_id,
                title=self.title,
                description="Dangerous pattern detected",
                severity=Severity.HIGH,
                owasp_mcp=self.owasp_mapping,
                server_name=server.name,
                location="config",
                remediation="Remove the dangerous pattern.",
                references=["https://owasp.org/www-project-mcp-top-10/"],
            ))
        return findings

# Use with the engine
from mcpshield.scanner.engine import ScanEngine
from mcpshield.scanner.rules import DEFAULT_RULES

engine = ScanEngine(rules=DEFAULT_RULES + [MyCustomRule])

Security Score

MCPGuard computes a score from 0-100:

Score Rating
90-100 EXCELLENT
70-89 GOOD
50-69 FAIR
25-49 POOR
0-24 CRITICAL

Each CRITICAL finding deducts 25 points, HIGH deducts 15, MEDIUM deducts 8, LOW deducts 3.


References


Contributing

Issues and pull requests welcome at github.com/aryanjp1/mcpguard.

To run the test suite:

pip install -e ".[dev]"
pytest --cov

To add a new rule, create a file in src/mcpshield/scanner/rules/, extend BaseRule, and add it to DEFAULT_RULES in src/mcpshield/scanner/rules/__init__.py.


License

MIT — see LICENSE.

Metadata

Release files for mcpguard 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcpguard 0.1.0
File Size Uploaded Provenance
mcpguard-0.1.0.tar.gz 62.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mcpguard 0.1.0
File Interpreter ABI Platform
mcpguard-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 135.4 kB

Release files / mcpguard-0.1.0.tar.gz

Download URL mcpguard-0.1.0.tar.gz
Size 62.7 kB
Tags Source
SHA-256 checksum
How to use checksums
03993decc764f392358f7e99b2851d64e6084cf6a151ae06a1a5904eb4dcb1ce
BLAKE2b-256 checksum
How to use checksums
bfbca52ca1668477496b9b350307f7d77605f2253a9a19c5d6a075fe1a2d1e50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.16

Release files / mcpguard-0.1.0-py3-none-any.whl

Download URL mcpguard-0.1.0-py3-none-any.whl
Size 72.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e920524a5b67641c64a501536d1ceb612228174e13179d143961ecff6781034
BLAKE2b-256 checksum
How to use checksums
0386a74334b82da6558d1c420ecbcca7a271a3c4b40003b6910f0734d81e93fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.16

Security for mcpguard 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page