Skip to main content

mcplens

An MCP server security scanner that doesn't just read what a server claims — it tests what the server actually does.

Static scanners for the Model Context Protocol (MCP) read tool descriptions and configs. That's table stakes, and mcplens does it too. But a tool description is a claim, and the worst MCP attacks — tool poisoning, rug pulls, confused-deputy tools — are lies told in exactly those claims.

mcplens adds runtime behavioral verification:

  • It launches the server in a sandbox whose HOME is stocked with canary credential files (a fake ~/.ssh/id_rsa, fake AWS credentials — each with a unique token).
  • It invokes every tool once with safe, schema-derived benign inputs.
  • It watches what actually happens: canary tokens leaking into responses, writes to the filesystem from "read-only" tools, network requests the description never mentions.
  • Every probed tool gets a declared-vs-observed report card.

And because servers change after you approve them, mcplens baselines tool definitions with SHA-256 hashes and diffs them later — the rug-pull watch.

Maintained by Karmendra Pandey. MIT licensed.

Install

pip install mcplens-scanner        # (PyPI release pending; for now install from source)
git clone https://github.com/karmendra8386/mcplens && cd mcplens
pip install -e .

Requires Python 3.10+ and the official mcp Python SDK (installed automatically).

Usage

Scan a server (static rules)

# stdio server by command
mcplens scan --cmd "python my_server.py"

# from a client config (Claude Desktop / mcpServers format)
mcplens scan --config ~/.config/claude/claude_desktop_config.json --name my-server

# remote streamable-HTTP server
mcplens scan --url https://example.com/mcp

Scan with behavioral probes (stdio servers)

mcplens scan --probes --cmd "python my_server.py"

Probes run the server with HOME and the working directory pointed at a throwaway sandbox. Your real files are never touched, probes never pass destructive payloads, tools with free-form command parameters are never exercised, and destructive-looking tools are skipped and reported as not probed.

Machine-readable output:

mcplens scan --probes --format json --cmd "python my_server.py"

Exit code is 1 when any critical finding is present, 0 otherwise — CI-friendly.

Baseline & rug-pull diff

mcplens baseline --cmd "python my_server.py"          # writes mcplens-baseline.json
# ...later, after the server updates...
mcplens diff --cmd "python my_server.py"              # exit 1 if definitions drifted

The baseline stores the SHA-256 of every tool's canonical definition (name + description + input schema) plus a whole-set hash. diff reports added, removed, and changed tools, with the changed fields named.

What it catches

Sample output against the deliberately vulnerable fixture in fixtures/:

Findings: 5 (critical 4, high 1, medium 0, low 0, info 0)
  [CRITICAL] MCPL001 (static) add: Instruction injection in tool description
  [CRITICAL] MCPL003 (static) add: Tool description references sensitive files
  [CRITICAL] MCPL101 (probe) get_system_info: Tool returned canary credential contents
  [CRITICAL] MCPL103 (probe) get_system_info: Read-only-claimed tool modified the filesystem
  [HIGH    ] MCPL005 (static) run_command: Unconstrained shell/command parameter

Behavioral probes (declared vs observed):
  - get_system_info: declared [read-only access] | observed [returned a response;
      returned contents of canary file(s): .ssh/id_rsa;
      filesystem changes: home/.mcplens_was_here]

Grade: F  (score 0/100)

Note what happened there: get_system_info looks clean to static analysis — its description is a lie, and only running it exposes the lie. That gap is why mcplens exists.

Rule catalog

Static rules (see docs/rule-catalog.md):

ID Severity Check OWASP MCP Top 10
MCPL001 critical Instruction injection in tool description MCP05 Tool Poisoning
MCPL002 high Hidden / bidirectional Unicode in tool definition MCP05 Tool Poisoning
MCPL003 critical Description references sensitive files (~/.ssh, .env, …) MCP05 Tool Poisoning
MCPL004 medium Look-alike tool names (possible shadowing) MCP05 Tool Poisoning
MCPL005 high Unconstrained shell/command parameter MCP04 Command Injection
MCPL006 medium Parameter with no type constraint MCP09 Protocol & Transport
MCPL007 medium Schema allows arbitrary additional properties MCP06 Privilege Escalation
MCPL008 medium Read-only-sounding tool describes write/exec behavior MCP06 Privilege Escalation
MCPL009 low Excessive tool count (> 50) MCP02 Context Over-Sharing
MCPL010 high Duplicate tool names MCP05 Tool Poisoning
MCPL011 medium Description claims broad data access MCP02 Context Over-Sharing
MCPL012 low Unusually long description (> 2000 chars) MCP05 Tool Poisoning
MCPL013 medium Server reached over plaintext HTTP MCP09 Protocol & Transport
MCPL014 medium Tool accepts a secret as a plain parameter MCP01 Token Mismanagement
MCPL015 low Tool has no description MCP08 Audit Logging

Behavioral probe findings:

ID Severity Check OWASP MCP Top 10
MCPL101 critical Tool returned canary credential contents MCP02 Context Over-Sharing
MCPL102 high Tool modified the filesystem without declaring it MCP06 Privilege Escalation
MCPL103 critical Read-only-claimed tool modified the filesystem MCP06 Privilege Escalation
MCPL104 high Tool made an undeclared network request MCP02 Context Over-Sharing
MCPL105 low Tool errored under benign probe input MCP08 Audit Logging

Each server is graded A–F from its findings (critical −40, high −20, medium −8, low −3).

How the probes work

  1. Sandbox. A temp directory becomes the server's HOME and working directory. It contains canary files: .ssh/id_rsa, .aws/credentials, canary_note.txt, Documents/finances.txt — each holding a unique MCPLENS-CANARY-… token.
  2. Argument derivation. For each tool, arguments are derived from its input schema: strings get harmless placeholders, URL parameters get the URL of a local one-shot HTTP listener, integers get 1, and so on. Tools whose names suggest destructive operations, and tools with free-form command parameters, are never invoked.
  3. Observation. The sandbox filesystem is hashed before and after each invocation, so writes are attributed to the exact tool that made them. Responses are searched for canary tokens. Listener hits reveal network egress, which is only a finding when the description doesn't declare network use.
  4. Report card. Each tool's inferred declared behaviors (from its name and description) are printed next to what was observed.

Development

python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest

The test suite runs against two fixture servers in fixtures/: benign_server.py (honest tools — must stay clean) and vulnerable_server.py (a poisoned description, a behaviorally lying "read-only" tool, and a raw shell tool — test fixture only, never deploy it).

Roadmap

  • v0.2 — SARIF output for CI dashboards; schema-fuzzing probes (boundary/malformed inputs); probing of remote HTTP servers in an isolated environment.
  • Research — a registry-scale behavioral study: run mcplens against the most popular public MCP servers and publish how many tools do more than their descriptions claim ("Do MCP Tools Do What They Say?").
  • Signed tool-definition registries and continuous rug-pull monitoring.

Responsible use

mcplens' probes are benign canaries meant for servers you own or are authorized to test. Pointing any scanner at third-party servers beyond their public tool interface is out of scope.

License

MIT — see LICENSE. Author and maintainer: Karmendra Pandey.

Metadata

Release files for mcplens-scanner 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 mcplens-scanner 0.1.0
File Size Uploaded
mcplens_scanner-0.1.0.tar.gz 25.6 kB Details

Built distribution (wheel)

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

Total release size: 50.1 kB

Release files / mcplens_scanner-0.1.0.tar.gz

Download URL mcplens_scanner-0.1.0.tar.gz
Size 25.6 kB
Tags Source
SHA-256 checksum
How to use checksums
9edb33c6677607a9e59346924c4cebb643f3e17c6ad3bf091637e80a565ad780
BLAKE2b-256 checksum
How to use checksums
3ca74b0f2323342bf65d9b3e550447ab74cefc0b4718138c8068de52197a4b61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 11, 2026.

Transparency log

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

Download URL mcplens_scanner-0.1.0-py3-none-any.whl
Size 24.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c82beb08c3d51185f17df326c0a86bfd874bdca5bda88dda7a19ad95980ce077
BLAKE2b-256 checksum
How to use checksums
ccd83f5bdf41c2cb77ff8f171e40216b0175a71701c526aaa40a413bf108599d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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