# Cisco MCP Scanner Plugin

> Draft · awaiting review.

> Claude Code plugin that scans MCP servers and tools for prompt injection, tool poisoning and other risks via the Cisco MCP scanner.

- Badge: `reach 3 · beyond declared (1)`
- Type: Plugin; tier: tried
- Tasks: Agent supply-chain scan; mission: Agent security; works with: Claude Code
- Source: https://github.com/cisco-ai-defense/mcp-scanner (claude-code-plugin), pinned to `5d147dc` (v4.8.6), licence Apache-2.0
- Last checked: 2026-11-07; next check: 2027-05-06; method v0.1, reach-v0.1

## At a glance

- **What it is:** A Claude Code plugin whose slash commands and skill have Claude run Cisco's mcp-scanner CLI to check MCP servers, tools, prompts and resources for prompt injection, tool poisoning and other threats with YARA rules, an LLM and the Cisco AI Defense API. A plugin bundles skills, commands, hooks or MCP servers for one AI client.
- **Made for:** Scan MCP servers and tools for security threats and risks from inside Claude Code. +2 more
- **Runs:** Inside your AI client: its model follows the instructions and works with the client's own tools. Other modes: stand-alone CLI (on your machine, started by you); REST API server (on your machine, as a service with a network port). Listens only in an optional mode: mcp-scanner-api serves the REST scan endpoints on 127.0.0.1:8000 by default; --host and --port change the address (no sign-in).
- **Sends data to:** Remote MCP server (named URL) (by default), Remote servers listed in client configs (if you turn it on), LLM provider via LiteLLM (if you turn it on), Cisco AI Defense inspect API (if you turn it on), Package registries of launched servers (if you turn it on), mcp.deepwiki.com (if you turn it on), VirusTotal (if you turn it on). Other connections not ruled out: read in the documentation and the cited code, not searched in full.
- **Can change things:** Changes, runs commands, sends data out, according to the capabilities read. Partly listed: CLI features the plugin does not wrap: virustotal, pypi-scan, npm-scan (Docker), vulnerable-package --fix, readiness, prompt_defense, meta, REST API server
- **Needs:** Claude Code, which loads the plugin from its folder with --plugin-dir · The cisco-ai-mcp-scanner Python package, installed separately from the plugin · Python 3.11.4 or newer · +4 more

Profile read at commit `5d147dc` on 2026-10-25; every fact cites a file and line at that commit.

## What it does

A Claude Code plugin whose slash commands and skill have Claude run Cisco's mcp-scanner CLI to check MCP servers, tools, prompts and resources for prompt injection, tool poisoning and other threats with YARA rules, an LLM and the Cisco AI Defense API. (claude-code-plugin/skills/security-scan/SKILL.md#L3)

Made for (the author says):

- Scan MCP servers and tools for security threats and risks from inside Claude Code. (claude-code-plugin/README.md#L3)
- Detect prompt injection, tool poisoning and other threats in MCP tools, prompts and resources. (claude-code-plugin/.claude-plugin/plugin.json#L3)
- Detect malicious MCP tools by combining the Cisco AI Defense inspect API, YARA rules and LLM-based analysis. (README.md#L10)

Documented uses:

- Scan new MCP servers before adding them to a client configuration [Agent supply-chain scan] (claude-code-plugin/skills/security-scan/SKILL.md#L239)
- Rescan existing MCP client configurations periodically for new threats [Agent supply-chain scan] (claude-code-plugin/skills/security-scan/SKILL.md#L240)
- Analyze MCP server source code for mismatches between documentation and implementation [Code review and static analysis (SAST)] (claude-code-plugin/skills/security-scan/SKILL.md#L130)
- Scan pre-generated tools, prompts and resources JSON files in CI/CD without a live server [Agent supply-chain scan] (claude-code-plugin/skills/security-scan/SKILL.md#L152)

## What it can do

| Group | What it covers | Effect | On by default |
|---|---|---|---|
| quick-scan, scan-remote | Run mcp-scanner with the YARA analyzer against a remote MCP server URL and report a summary (quick-scan) or details (scan-remote). (claude-code-plugin/commands/quick-scan.md#L9-13) | reads, runs commands | yes |
| deep-scan | Run the YARA, LLM and Cisco AI Defense API analyzers against a remote MCP server and report findings by severity. (claude-code-plugin/commands/deep-scan.md#L11) | reads, runs commands, sends data out | yes |
| scan-known-configs | Scan the servers defined in the well-known MCP config files of Windsurf, Cursor, Claude Desktop and VS Code with the YARA analyzer. (claude-code-plugin/commands/scan-known-configs.md#L11-18) | reads, runs commands | yes |
| scan-config | Scan every MCP server defined in one config file given by path with the YARA analyzer. (claude-code-plugin/commands/scan-config.md#L11) | reads, runs commands | yes |
| scan-prompts, scan-resources | Fetch the prompts or resources of a remote MCP server and check them with the LLM analyzer. (claude-code-plugin/commands/scan-prompts.md#L11) | reads, runs commands, sends data out | yes |
| scan-behavioral | Analyze MCP server source code in a file or directory for docstring-versus-implementation mismatches with the LLM-backed behavioral analyzer. (claude-code-plugin/commands/scan-behavioral.md#L14-19) | reads, runs commands, sends data out | yes |
| mcp-security-scan | Skill Claude uses on MCP security requests; adds launching and scanning stdio MCP servers, server-instruction scans and combined analyzers to the commands. (claude-code-plugin/skills/security-scan/SKILL.md#L74-75) | reads, runs commands, sends data out | yes |
| pypi-scan, npm-scan | Download a PyPI or npm package and scan it with behavioral analysis, inside a Docker sandbox by default or in-process with --no-docker. (README.md#L289-290) | reads, runs commands | yes |
| vulnerable-package | Check a requirements file or project for known vulnerable Python dependencies using PyPI or OSV data; --fix changes the vulnerable dependencies automatically. (README.md#L531-540) | reads, changes | yes |

Partly listed: CLI features the plugin does not wrap: virustotal, pypi-scan, npm-scan (Docker), vulnerable-package --fix, readiness, prompt_defense, meta, REST API server

## How it runs

Markdown slash commands and a skill in Claude Code have the model run the local mcp-scanner Python CLI; the CLI reaches remote MCP servers over SSE or streamable HTTP, starts stdio servers as child processes, and can send content to an LLM provider via LiteLLM or to the Cisco AI Defense API. (claude-code-plugin/skills/security-scan/SKILL.md#L35)

- Starts: Inside your AI client: its model follows the instructions and works with the client's own tools. Runs as Claude Code commands and a skill; the model executes the separately installed mcp-scanner CLI on the local machine. (claude-code-plugin/skills/security-scan/SKILL.md#L8)
- Can also run: On your machine, started by you (stand-alone CLI, switch `mcp-scanner`). The mcp-scanner CLI also runs on its own from a terminal, outside Claude Code. (README.md#L23)
- Can also run: On your machine, as a service with a network port (REST API server, switch `mcp-scanner-api`). mcp-scanner-api starts a FastAPI REST server that exposes the scan functions as HTTP endpoints. (README.md#L713)
- Your AI client: **Plugin commands and skill**: Slash commands under the mcp-scanner: namespace and the mcp-security-scan skill that tell Claude which mcp-scanner command to run. (claude-code-plugin/README.md#L39)
- Your machine: **mcp-scanner CLI**: Python package cisco-ai-mcp-scanner; the mcp-scanner entry point runs the analyzers and the MCP client connections. (pyproject.toml#L120)
- Your machine: **stdio MCP servers**: Local MCP server programs the scanner starts as child processes over stdio to list their tools. (mcpscanner/core/scanner.py#L2366-2374)
- Outside your machine: **Remote MCP servers**: SSE or streamable HTTP MCP servers named by URL or found in client configs; their tools, prompts, resources and instructions are read. (README.md#L281)
- Outside your machine: **LLM provider**: Model reached through LiteLLM for the llm and behavioral analyzers, for example OpenAI, Azure OpenAI, AWS Bedrock or a local endpoint. (README.md#L129)
- Outside your machine: **Cisco AI Defense API**: Cisco inspect API used by the api analyzer; the default endpoint is in the US region and MCP_SCANNER_ENDPOINT changes it. (README.md#L106)
- Listens: mcp-scanner-api serves the REST scan endpoints on 127.0.0.1:8000 by default; --host and --port change the address.: an address you choose, no sign-in, in an optional mode (mcpscanner/config/constants.py#L63-64)
- Sends data to Remote MCP server (named URL) (your targets, by default): Connects to the server URL passed to a command to list and read its tools, prompts, resources or instructions. (claude-code-plugin/commands/scan-remote.md#L11)
- Sends data to Remote servers listed in client configs (your targets, if you turn it on): Config scans connect to each remote server listed in the scanned MCP client config files. (mcpscanner/core/scanner.py#L2678-2683)
- Sends data to LLM provider via LiteLLM (model provider, if you turn it on): Sends tool descriptions, prompt or resource text, or source code as chat messages when the llm or behavioral analyzer runs. (mcpscanner/core/analyzers/llm_analyzer.py#L649)
- Sends data to Cisco AI Defense inspect API (vendor API, if you turn it on): Sends content to the Cisco AI Defense inspect API with the key in the X-Cisco-AI-Defense-API-Key header when the api analyzer runs. (mcpscanner/core/analyzers/api_analyzer.py#L86)
- Sends data to Package registries of launched servers (download, if you turn it on): Stdio servers launched through commands such as uvx can download their dependencies on first run. (README.md#L167)
- Sends data to mcp.deepwiki.com (your targets, if you turn it on): When the CLI runs without a target, --server-url defaults to https://mcp.deepwiki.com/mcp. (mcpscanner/cli.py#L1580-1584)
- Sends data to VirusTotal (vendor API, if you turn it on): The virustotal subcommand and analyzer look up file SHA256 hashes at VirusTotal; they are enabled whenever VIRUSTOTAL_API_KEY is configured unless MCP_SCANNER_VIRUSTOTAL_ENABLED is false. (README.md#L145-154)

## What you need

- Runtime: Claude Code, which loads the plugin from its folder with --plugin-dir. (claude-code-plugin/README.md#L32)
- Other tools: The cisco-ai-mcp-scanner Python package, installed separately from the plugin. (claude-code-plugin/README.md#L16-18)
- Runtime: Python 3.11.4 or newer. (pyproject.toml#L16)
- Other tools: uv, because the skill tells Claude to start the scanner with uv run mcp-scanner. (claude-code-plugin/skills/security-scan/SKILL.md#L10)
- Model key: MCP_SCANNER_LLM_API_KEY for the llm and behavioral analyzers used by deep-scan, scan-prompts, scan-resources and scan-behavioral. (claude-code-plugin/README.md#L67-68)
- Credentials: MCP_SCANNER_API_KEY for the Cisco AI Defense api analyzer. (claude-code-plugin/README.md#L69)
- Account: A Cisco AI Defense subscription for the api analyzer. (README.md#L814)
- Installer: The plugin loads from a local folder with claude --plugin-dir; the README names a marketplace install for when the plugin is published. (claude-code-plugin/README.md#L29-35)
- Installer: pip install cisco-ai-mcp-scanner installs the latest package release without a version pin. (claude-code-plugin/README.md#L18)
- Installer: The main README installs the CLI as a uv tool with Python 3.13, unpinned, or from the GitHub repository with --from git+. (README.md#L53-61)
- Installer: The folder passed to claude --plugin-dir is the claude-code-plugin directory of the mcp-scanner repository, which the README fetches with git clone. (README.md#L67)
- Installer: The cisco-ai-mcp-scanner package build includes only the mcpscanner modules, so pip install does not provide the plugin folder. (pyproject.toml#L141-142)

## Limits and risks

- The known-configs scan reads MCP client config files in the home directory, on Windows including Claude Desktop's claude_desktop_config.json and VS Code's settings.json. (mcpscanner/config/constants.py#L392-400)
- Config scans start each stdio server listed in the scanned file to list its tools. (mcpscanner/core/scanner.py#L2658-2662)
- Stdio servers start with the scanner's full process environment merged with the env entries from their config. (mcpscanner/core/scanner.py#L2364-2370)
- A --bearer-token given to known-configs or config is sent to every remote server discovered in the configs. (README.md#L348-351)
- Without --analyzers the CLI runs api, yara and llm, so content goes to Cisco and the LLM provider when their keys are set. (mcpscanner/cli.py#L1533-1537)
- The README starts the REST API with --host 0.0.0.0, which binds it to all interfaces. (README.md#L716)
- The REST /scan-tool handler's parameters are the request body, the incoming HTTP request and a scanner factory; its signature has no authentication dependency. (mcpscanner/api/router.py#L392-401)
- The author states that behavioral analysis cannot detect runtime-only behaviors and may miss heavily obfuscated code. (docs/behavioral-scanning.md#L364-365)
- MCP_SCANNER_VIRUSTOTAL_UPLOAD_FILES uploads unknown files to VirusTotal for scanning; the documented default is false. (README.md#L156-157)
- The REST /scan-tool endpoint connects to the server_url named in the request body, with API-key or custom-header auth also taken from that body. (mcpscanner/api/router.py#L420-429)
- Config scans connect to each remote server with its URL and the auth given on the command line only; headers stored for that server in the scanned config file are not sent. (mcpscanner/core/scanner.py#L2681-2682)
- The CLI sets the Cisco AI Defense key only when the api analyzer is selected and the LLM key only for the llm, behavioral or meta analyzers, so scans run with --analyzers yara call neither service. (mcpscanner/cli.py#L205-214)

## Rights in plain language

- Declared: files 1 (reads outside the project), network 1 (talks only to declared hosts), execution 2 (runs shell commands or eval), secrets 3 (reads credential stores).
- Code: reach 3 (privileged): network 2 (talks to any host), execution 2 (runs shell commands or eval), secrets 3 (reads credential stores), persistence 2 (changes config or installs globally); unknown: approval.
- Lab: Beyond declared on 1 of 6 rights: network (observed 2, declared 1), with blocked attempts to reach GitHub at start-up even in YARA-only mode.

Why three columns? Declarations are often incomplete and scanners can be bypassed, so we run each tool once and compare.

## Privilege Reach

Reach level 3 (privileged).

| Right | Declared | Code | Lab |
|---|---|---|---|
| Files: where does it read and write? | 1 reads outside the project | 1 reads outside the project | ? unknown |
| Network: whom does it talk to? | 1 talks only to declared hosts | 2 talks to any host | 2 talks to any host (beyond declared) |
| Execution: what does it run? | 2 runs shell commands or eval | 2 runs shell commands or eval | 0 runs no programs |
| Secrets: which credentials does it touch? | 3 reads credential stores | 3 reads credential stores | 0 touches no credentials |
| Persistence: what survives the run? | not declared | 2 changes config or installs globally | 0 leaves results only |
| Approval: does it ask before acting? | not declared | ? unknown | ? unknown |

0 contained · 1 scoped · 2 open · 3 privileged · ? no evidence · 0 never means safe

## Install

### Upstream

Quoted from `claude-code-plugin/README.md#L18-32` at the pinned commit (not a command to copy): `pip install cisco-ai-mcp-scanner
claude --plugin-dir /path/to/claude-code-plugin`


### Run it with least privilege

- claude code: `run the yara analyzer only (no API keys, no cloud upload); avoid --scan-known-configs and the stdio launch mode unless you trust every server in your local configs; remove scanner and LLM API keys from the environment before a known-configs scan, because every started server inherits it`
- note: `derived from the code; of it, the lab ran the YARA-only CLI without keys (runs/2026-11-07), not the plugin path`

- derived, not tested: proposed from the code analysis

## Lab runs

### 2026-11-07

One run is an observation, not a benchmark.

- Run and written by Ilja Schlak, 2026-11-07
- Target: Lab fixture vuln-mcp-server (MCP over streamable HTTP) 0.1.0; no model; standalone mode n/a (no approval layer); white-box
- Verdict: Beyond declared on 1 of 6 rights: network (observed 2, declared 1), with blocked attempts to reach GitHub at start-up even in YARA-only mode.
- Use again: with-limits; Useful as a key-free first pass over an MCP server's tools: it flagged all three baited tools without a false alarm, but it reads tools only and reaches for GitHub at start-up.
- Artifacts: https://readbeforerun.ai/catalog/cisco-mcp-scanner/runs/2026-11-07/

## Questions and answers

**Why compare declared, code and lab?**

Declarations are often incomplete and scanners can be bypassed, so we run each tool once and compare.

**What rights does Cisco MCP Scanner Plugin declare?**

files 1 (reads outside the project), network 1 (talks only to declared hosts), execution 2 (runs shell commands or eval), secrets 3 (reads credential stores).

**What does its code suggest?**

reach 3 (privileged): network 2 (talks to any host), execution 2 (runs shell commands or eval), secrets 3 (reads credential stores), persistence 2 (changes config or installs globally); unknown: approval.

**What did it use when it ran in the lab?**

Beyond declared on 1 of 6 rights: network (observed 2, declared 1), with blocked attempts to reach GitHub at start-up even in YARA-only mode.

**Was it tried, and when?**

Yes: 2026-11-07.

**What changed since the last check?**

Upstream last pushed 2026-10-16; 0 release(s) since the pinned version.

**How do I run it with least privilege?**

Derived, not tested: claude_code: run the yara analyzer only (no API keys, no cloud upload); avoid --scan-known-configs and the stdio launch mode unless you trust every server in your local configs; remove scanner and LLM API keys from the environment before a known-configs scan, because every started server inherits it; note: derived from the code; of it, the lab ran the YARA-only CLI without keys (runs/2026-11-07), not the plugin path

Method: https://readbeforerun.ai/method/
