Skip to main content

nyuwaymcpscanner

CI PyPI Python License

Enterprise-grade security scanner for Model Context Protocol (MCP) servers.

Catches hardcoded secrets, tool-poisoning instructions, supply-chain attacks, shell-execution backdoors, and data-exfiltration endpoints before they reach production - entirely offline, with no data leaving your machine.

pip install nyuwaymcpscanner
nyuwaymcpscanner scan ./my-mcp-server

Why nyuwaymcpscanner?

MCP servers run with broad access to files, shells, and network sockets on behalf of AI agents. A compromised or malicious MCP server can:

  • Exfiltrate secrets and conversation history to attacker-controlled webhooks
  • Inject hidden instructions into tool descriptions to hijack agent behaviour ("tool poisoning")
  • Execute arbitrary shell commands through unsanitized tool inputs
  • Pull in typosquatted dependencies that install malware at install time

nyuwaymcpscanner gives you a repeatable, CI-friendly audit layer that catches these threats statically - no runtime required.


Quick start

# Install
pip install nyuwaymcpscanner

# Scan a local server directory
nyuwaymcpscanner scan ./my-mcp-server

# Scan a single file directly
nyuwaymcpscanner scan ./mcp.json
nyuwaymcpscanner scan ./config.py

# Scan a package from npm or PyPI
nyuwaymcpscanner scan npm:@modelcontextprotocol/server-github
nyuwaymcpscanner scan pypi:weather-mcp

# Scan a GitHub repository
nyuwaymcpscanner scan github:owner/repo

# Scan a claude_desktop_config.json (all declared servers at once)
nyuwaymcpscanner scan ~/Library/Application\ Support/Claude/claude_desktop_config.json --config

# CI: fail the build when HIGH or above findings are found
nyuwaymcpscanner scan ./server --offline --static-only --fail-on high

Sample output

 Baseline Scan - ./my-mcp-server
+--------------+-------------------------------------------------------------------+
| Risk Score   | 85 / 100                                                          |
| Verdict      | HIGH                                                              |
| Files scanned| 12                                                                |
+--------------+-------------------------------------------------------------------+

Findings
+----+--------------------+----------+---------------------------------------------+
| #  | Type               | Severity | Evidence                                    |
+----+--------------------+----------+---------------------------------------------+
| 1  | hardcoded_secret   | HIGH     | AWS_ACCESS_KEY_ID = "AKIA..."  config.py:1  |
| 2  | yara_match         | HIGH     | os.system call in tool logic   tool.py:4    |
+----+--------------------+----------+---------------------------------------------+

Scan modes

Baseline scan (default, fully offline)

The Baseline scan runs entirely on your machine. It makes zero external network calls - no telemetry, no cloud APIs, no data leaves your environment.

Three static layers run in sequence:

Layer What it catches
Secrets Hardcoded AWS/GCP/Azure keys, OpenAI/Anthropic tokens, private keys, JWT secrets, generic passwords
YARA rules Tool-poisoning instructions, external logging endpoints, shell execution, plaintext passwords, internal IP leakage
Supply chain Typosquatted dependency names (edit-distance 1 from popular packages); CVE lookup via OSV.dev (skipped in --offline mode)
VirusTotal SHA256 hash lookup for binary files against 70+ AV engines - no file upload, hash only (skipped when VIRUSTOTAL_API_KEY is not set)

A fifth local LLM layer runs semantic analysis of MCP tool manifests using a locally-hosted Ollama model (skipped with --static-only).

# Static only - no Ollama required, suitable for CI without GPU
nyuwaymcpscanner scan ./server --static-only --offline

# With LLM analysis - requires Ollama running locally
nyuwaymcpscanner scan ./server --offline

Running with LLM analysis

One-time setup to install Ollama and pull the model (~5GB):

nyuwaymcpscanner setup

Then scan without --static-only:

# Full Baseline: static + local LLM, fully air-gapped
nyuwaymcpscanner scan ./my-mcp-server --offline

# Single manifest file with LLM analysis
nyuwaymcpscanner scan ./mcp.json --offline

The LLM layer only activates when an mcp.json manifest is present. If Ollama is not running, the scan falls back to static-only with a warning - it never fails hard.

Requirements: ~8GB RAM, Ollama installed via nyuwaymcpscanner setup.

VirusTotal malware detection

nyuwaymcpscanner can hash-check binary files (wheels, archives, executables, DLLs) against VirusTotal's 70+ AV engines. Only the SHA256 hash is sent - no file content ever leaves your machine.

Setup (free, takes 2 minutes):

  1. Create a free account at virustotal.com
  2. Go to your profile and copy your API key
  3. Set it once in your environment:
export VIRUSTOTAL_API_KEY=your_key_here

Then scan normally - VirusTotal runs automatically on any binary files found:

nyuwaymcpscanner scan npm:some-package
nyuwaymcpscanner scan github:owner/repo
nyuwaymcpscanner scan ./my-mcp-server

If binaries are found but no key is set, the scanner prints a reminder:

Note: 3 binary files not checked for malware - set VIRUSTOTAL_API_KEY for hash-based detection (free at virustotal.com).

You can also pass the key inline for one-off scans:

nyuwaymcpscanner scan ./server --vt-key YOUR_KEY

VirusTotal is skipped automatically when --offline is set. Free tier allows 500 lookups per day.


Scanning a single file

When the target is a single file, findings are scoped to that file only - sibling files in the same directory are ignored:

# Scan a single mcp.json
nyuwaymcpscanner scan ./mcp.json --offline --static-only

# Scan a single source file
nyuwaymcpscanner scan ./server.py --offline --static-only

# Scan a requirements file (CVE lookup runs against its dependencies)
nyuwaymcpscanner scan ./requirements.txt --static-only
Target type Recommended command
Single mcp.json or .py scan ./file --offline --static-only
Full server directory scan ./my-server --offline
requirements.txt / package.json scan ./requirements.txt --static-only
Claude Desktop config scan ./claude_desktop_config.json --config --offline --static-only

Deep Scan (invite only)

Deep Scan is a Nyuway-hosted analysis tier that performs frontier-model semantic analysis, cross-tool exfiltration detection, and behavioral mismatch analysis. It is currently available by invite.

nyuwaymcpscanner scan ./server --deep --token YOUR_TOKEN

Join the waitlist: https://forms.gle/bH8nToK9Zh7ey5F46


CLI reference

nyuwaymcpscanner scan TARGET [OPTIONS]

TARGET
  ./path/to/server     Local directory
  ./path/to/file.py    Single file (findings scoped to that file only)
  ./mcp.json           Single manifest file
  github:owner/repo    GitHub repository (optionally @ref)
  npm:package@version  npm package
  pypi:package@version PyPI package
  /path/to/config.json MCP host config file (requires --config)
  /path/to/list.txt    Newline-delimited list of targets (requires --batch)

Options
  --offline        Disable all outbound network calls (OSV.dev CVE lookup skipped)
  --static-only    Skip local LLM layer; run secrets + YARA + supply chain only
  --output FORMAT  Output format: summary (default), json, sarif
  --fail-on LEVEL  Exit non-zero when verdict >= LEVEL (low/medium/high/critical)
  --config         Treat TARGET as an MCP host config file; scan all declared servers
  --batch          Treat TARGET as a newline-delimited list of server paths
  --deep           Run Deep Scan (invite only; requires --token)
  --token TOKEN    Deep Scan invite token
  --model MODEL    Ollama model for local LLM layer (default: llama3)
  --vt-key KEY     VirusTotal API key for binary malware detection (or set VIRUSTOTAL_API_KEY)

nyuwaymcpscanner setup
  Download and verify the local Ollama model for LLM-assisted scanning.

Output formats

Summary (default)

Rich terminal table with colour-coded severity, suitable for interactive use.

JSON (--output json)

Machine-readable report. Stable schema for scripting and dashboards.

{
  "tool": "nyuwaymcpscanner",
  "version": "0.1.0",
  "target": "./server",
  "scanned_at": "2025-01-15T10:30:00Z",
  "risk_score": 85,
  "verdict": "HIGH",
  "findings": [
    {
      "type": "hardcoded_secret",
      "severity": "high",
      "weight": 30,
      "file": "config.py",
      "line": 1,
      "pattern": "AWS Access Key ID",
      "evidence": "AWS_ACCESS_KEY_ID = \"AKIA...\"",
      "source": "secrets_scanner"
    }
  ]
}

SARIF (--output sarif)

SARIF 2.1.0 format for GitHub Advanced Security, VS Code Problems panel, and any SARIF-aware CI tool.

# .github/workflows/mcp-scan.yml
- name: Scan MCP server
  run: |
    pip install nyuwaymcpscanner
    nyuwaymcpscanner scan ./server --offline --static-only --output sarif > results.sarif
- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

Scanning MCP host configs

Point nyuwaymcpscanner at your MCP host config to audit every server declared in it:

# Claude Desktop (macOS)
nyuwaymcpscanner scan \
  ~/Library/Application\ Support/Claude/claude_desktop_config.json \
  --config --offline

# Cursor / Windsurf / VS Code
nyuwaymcpscanner scan ~/.cursor/mcp.json --config --offline

Remote SSE/HTTP endpoints are reported as skipped (deep remote scanning is roadmapped for v1.1).


Local LLM setup

The LLM layer uses Ollama running locally. Run setup once:

# Install Ollama from https://ollama.ai, then:
nyuwaymcpscanner setup

This pulls the default model (llama3) and verifies connectivity. The LLM layer only runs when an mcp.json manifest is present in the scanned tree; it is silently skipped otherwise.


Verdicts and scoring

Verdict Score range Meaning
PASS 0 No findings
LOW 1-24 Informational; review but not urgent
MEDIUM 25-49 Should be fixed before production
HIGH 50-79 Block deployment
CRITICAL 80-100 Immediate action required

Each finding carries a weight (5-35). The final score is max(weight_sum, severity_floor) capped at 100.


What nyuwaymcpscanner catches

Finding type Severity Description
hardcoded_secret HIGH AWS/GCP/Azure credentials, API keys, private keys, JWT secrets
yara_match CRITICAL-LOW Tool-poisoning instructions, exfil endpoints, shell exec, passwords, internal IPs
typosquatting_risk MEDIUM Dependency name 1 edit-distance from a popular package
dependency_cve HIGH Known CVE in a pinned dependency (requires network; skipped with --offline)
tool_poisoning CRITICAL LLM-detected hidden instruction in tool description
malware_detected CRITICAL-MEDIUM Binary file flagged by VirusTotal AV engines (requires VIRUSTOTAL_API_KEY)

How nyuwaymcpscanner compares

Capability nyuwaymcpscanner Other MCP scanners
Hardcoded secret detection (8 types) yes partial
Shell execution patterns across 10 languages yes (50 patterns) Python/JS only
Supply chain CVE lookup (OSV.dev) yes partial
Typosquatting detection yes -
VirusTotal binary malware (hash only, no upload) yes partial
Tool poisoning / exfiltration instructions yes yes
Local LLM semantic analysis (fully offline) yes cloud only
Fully air-gapped / offline mode yes no
SARIF 2.1.0 output yes -
JSON output yes partial
Batch and host config file scanning yes -
Single-file scoped scanning yes -
Test/doc-aware false positive tuning yes -
Open, auditable detection rules (YARA) yes no
CI/CD fail-on severity gate yes -
Runtime proxy / tool pinning roadmap yes
Cloud behavioral analysis roadmap (Deep Scan) yes

Runtime proxy and behavioral analysis are complementary to static scanning - they operate at a different point in the deployment lifecycle. nyuwaymcpscanner is the pre-deploy static layer; runtime tools sit alongside it, not in place of it.


Requirements

  • Python 3.11+
  • Ollama (optional; only needed for LLM layer)

License

Apache 2.0. See LICENSE.


Metadata

Release files for nyuwaymcpscanner 0.2.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 nyuwaymcpscanner 0.2.0
File Size Uploaded Provenance
nyuwaymcpscanner-0.2.0.tar.gz 57.0 kB With provenance Details

Built distribution (wheel)

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

Total release size: 100.1 kB

Release files / nyuwaymcpscanner-0.2.0.tar.gz

Download URL nyuwaymcpscanner-0.2.0.tar.gz
Size 57.0 kB
Tags Source
SHA-256 checksum
How to use checksums
686c30edeff5c313be9474f1a876c4d8811c0ea76ebcf28e09648c45e82476f0
BLAKE2b-256 checksum
How to use checksums
cd507b2a32019fa8a3341fe15b9bc76eb2ed0c5f2d2f472a53de4eb09be4d8a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Release files / nyuwaymcpscanner-0.2.0-py3-none-any.whl

Download URL nyuwaymcpscanner-0.2.0-py3-none-any.whl
Size 43.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0b3a3add418463764ab1496f0912fdf75a385bb8dfb5afc0fa0bb998b9687580
BLAKE2b-256 checksum
How to use checksums
3081b8ee3ad0b3921da2e21fbd852fc43a8585c066db51cd6759672caed01a11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Security for nyuwaymcpscanner 0.2.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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for nyuwaymcpscanner-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

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.2.0 This release

2 release files Full 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