Skip to main content

Offline security checks for Model Context Protocol server configurations

Project description

mcp-check

Test Release License: MIT

Security linting for Model Context Protocol server configs before your AI agent runs them.

mcp-check is an offline static scanner for MCP configuration files. It shows when a config grants risky access to shell commands, local files, Docker, network destinations, package installers, or secrets.

It never launches or connects to an MCP server.

Documentation

Why

MCP configs can give AI coding agents access to terminals, repositories, filesystems, networks, Docker, and credentials. That is useful, but it also creates a review problem: a small JSON config can quietly grant a lot of power.

mcp-check makes those risks visible before execution.

Quick Demo

mcp-check scan examples/unsafe/docker-socket.json

Example output:

[HIGH] MCP container image is not immutable
  MCP004 args
  Evidence: docker example/mcp:latest

[CRITICAL] MCP server mounts the Docker socket
  MCP008 args.docker_socket
  Evidence: /var/run/docker.sock

[CRITICAL] MCP server requests privileged container execution
  MCP008 args.privileged

Install

From PyPI:

python -m pip install mcp-check-security

From a checkout:

python -m pip install .

For development:

uv run mcp-check scan examples/unsafe/docker-socket.json

Scan

mcp-check --version
mcp-check rules
mcp-check scan ./claude_desktop_config.json
mcp-check scan ./mcp.yaml
mcp-check scan ./mcp.toml
mcp-check scan ./claude_desktop_config.json --format json
mcp-check scan ./claude_desktop_config.json --format sarif --output results.sarif
mcp-check scan ./claude_desktop_config.json --fail-on high
mcp-check scan ./claude_desktop_config.json --suppressions ./examples/suppressions.json

The scanner supports JSON, YAML, and TOML files with an mcpServers object, including common Claude Desktop and Cursor-style shapes.

Client Presets

List common MCP client config paths:

mcp-check paths
mcp-check paths --preset claude-desktop
mcp-check paths --preset cursor --existing

Scan existing configs from known client locations:

mcp-check scan --preset all
mcp-check scan --preset claude-desktop
mcp-check scan --preset cursor

Example Configs

Use the example configs to see what each rule catches:

for file in examples/unsafe/*.json; do
  mcp-check scan "$file"
done

Examples included:

File Risk shown
examples/unsafe/leaked-secret.json plaintext API key
examples/unsafe/docker-socket.json privileged Docker and Docker socket
examples/unsafe/prompt-injection-description.json suspicious tool metadata
examples/unsafe/unpinned-npx.json mutable package install
examples/unsafe/http-remote-server.json insecure remote MCP URL
examples/unsafe/ssh-path-mount.json sensitive local path
examples/unsafe/git-main-install.json mutable Git branch install
examples/unsafe/shell-command.json shell and download execution
examples/unsafe/private-network-url.json SSRF, cloud metadata, and dangerous URL schemes
examples/unsafe/oauth-broad-scope.json broad OAuth scopes, HTTP OAuth URLs, and embedded client secret
examples/unsafe/local-http-transport.json local HTTP MCP transport requiring auth/origin hardening
examples/unsafe/wildcard-bind.json MCP server binding to all interfaces
examples/unsafe/oauth-token-query.json OAuth token in URL query and missing PKCE S256 metadata

GitHub Action

name: MCP security

on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: vigneshakaviki/mcp-check@v0.5.0
        with:
          paths: |
            config/claude_desktop_config.json
          suppressions: config/mcp-check-suppressions.json
          fail-on: high

Suppressions

Known findings can be suppressed explicitly by rule, server, and location. Suppressed findings are still visible in JSON and SARIF output.

{
  "suppressions": [
    {
      "rule_id": "MCP004",
      "server": "npx-demo",
      "location": "args",
      "reason": "Reviewed package source; pinning tracked separately."
    }
  ]
}

Use * for server or location only when the suppression really applies broadly.

Rules

ID Checks
MCP001 privileged, destructive, shell, download, or dynamic execution commands
MCP002 sensitive local paths such as SSH keys, cloud credentials, and .env files
MCP003 credentials embedded directly in configuration
MCP004 unpinned packages, mutable Git refs, and mutable container images
MCP005-MCP011 network, metadata, runtime, SSRF, OAuth, and transport risks

Findings include severity, confidence, evidence, location, and a remediation. Credential evidence is redacted in all reports.

See docs/rules.md or run mcp-check rules for the full rule catalog.

Terminal and JSON reports also include a capability summary for quick review:

Capabilities:
  shell: yes
  docker: yes
  network: https://example.test/install.sh
  packages: docker run --rm

These rules cover static signals from published MCP security research: tool poisoning, mutable supply-chain references, overbroad local privileges, static credentials, and weak transport. Runtime controls such as semantic approval, per-tool authorization, provenance signing, sandboxing, and audit logging still need to be enforced by the MCP client, gateway, or server runtime.

When To Use It

  • Before adding a new MCP server to Claude Desktop, Cursor, or an AI coding agent.
  • In pull requests that add or change MCP configs.
  • When reviewing an MCP server repo's example config.
  • Before sharing internal MCP setup snippets with a team.

Development

uv run --with 'pytest>=8' pytest -q
uv run mcp-check scan tests/fixtures/mixed.json

Roadmap

  • Baseline mode for existing findings.
  • More MCP client config path presets.
  • Publish to PyPI and Homebrew.
  • Optional provenance checks for known MCP server packages.

Security

This project performs static analysis only. Please report vulnerabilities through the process in SECURITY.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_check_security-0.5.0.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_check_security-0.5.0-py3-none-any.whl (26.8 kB view details)

Uploaded Python 3

File details

Details for the file mcp_check_security-0.5.0.tar.gz.

File metadata

  • Download URL: mcp_check_security-0.5.0.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mcp_check_security-0.5.0.tar.gz
Algorithm Hash digest
SHA256 818c76cf7665be24f918fd4e4b64bbd39fd2616869c1b865211831bab5d8ee83
MD5 ab41ea3c238830ca23833144c5fe6ed5
BLAKE2b-256 10e87c95176ebe8bdba98183efb8351f82eb83735c59d19d137aaec3e14706a5

See more details on using hashes here.

File details

Details for the file mcp_check_security-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_check_security-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 26.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mcp_check_security-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5205895941ee2301230e6b3ad90823821060a08458867ffbead9327328bce222
MD5 f7c246c589429075d287427e8708d401
BLAKE2b-256 535fc9168490b4e94db84c92ec7be8a894a1fd44dd4f14ccfa903caeb0d81dbd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page