Metadata-Version: 2.5
Name: aevrin
Version: 0.7.0
Summary: Aevrin MCP Security Scanner CLI: scan a source repository, local path, or live MCP server.
Project-URL: Homepage, https://mcp.aevrin.net
Project-URL: Documentation, https://mcp.aevrin.net/docs
Author: Aevrin
License-Expression: MIT
Keywords: mcp,model-context-protocol,scanner,security
Requires-Python: >=3.10
Requires-Dist: aevrin-scanner-core>=0.7.0
Requires-Dist: httpx>=0.27
Requires-Dist: rich>=13.9
Requires-Dist: typer>=0.15
Provides-Extra: mcp
Requires-Dist: mcp>=2.0; extra == 'mcp'
Provides-Extra: registry
Requires-Dist: pyyaml>=6; extra == 'registry'
Description-Content-Type: text/markdown

# aevrin

[![PyPI version](https://img.shields.io/pypi/v/aevrin.svg)](https://pypi.org/project/aevrin/)
[![Python versions](https://img.shields.io/pypi/pyversions/aevrin.svg)](https://pypi.org/project/aevrin/)
[![License](https://img.shields.io/pypi/l/aevrin.svg)](https://github.com/aevrin-projects/aevrin-mcp-scanner/blob/master/LICENSE)
[![Downloads](https://img.shields.io/pypi/dm/aevrin.svg)](https://pypi.org/project/aevrin/)
[![Publish status](https://github.com/aevrin-projects/aevrin-mcp-scanner/actions/workflows/publish.yml/badge.svg)](https://github.com/aevrin-projects/aevrin-mcp-scanner/actions/workflows/publish.yml)

Aevrin MCP Security Scanner CLI. Wraps the same open-source scanner binaries and normalization logic (`aevrin-scanner-core`) that the Aevrin backend uses, run locally against your own machine. Results save to your Aevrin dashboard automatically once you're logged in, pass `--no-upload` for a purely local, ephemeral scan.

## Install

```bash
python3 -m pip install --upgrade aevrin
```

The same CLI is also available through npm:

```bash
npm install --global aevrin
```

Requires Docker using Linux containers: a scan starts the MCP server inside one disposable,
version-pinned engine image, which is pulled automatically when missing. On Docker Desktop,
assign at least 4 GB of memory and permit bind mounts from the system temporary directory.
There is no non-Docker fallback - an unavailable sandbox is an unavailable scan, never a scan
performed without one - so use `--remote` for a local folder if you would rather not run Docker.

## Usage

```bash
aevrin scan mcp "npx -y @playwright/mcp"   # scan a server by its launch command
aevrin scan ./my-mcp-server
aevrin scan github.com/owner/repo
aevrin scan https://my-live-server.example.com --json
aevrin scan ./my-mcp-server --fail-on high
aevrin scan ./my-mcp-server --no-upload   # skip saving to your dashboard (e.g. in CI)
```

Target type is auto-detected: a `github.com` URL, another public `https://` URL as a live MCP
server, or anything that exists on disk as a local path. The same checks run either way - one
engine over the tools a live server actually returns, in five stages (`resolving`, `launching`,
`enumerating`, `analyzing`, `grading`) - and the target type only changes how `resolving` works
out what to start. Private, loopback, metadata, credential-bearing, and plain-HTTP live targets
are rejected. Aevrin never executes submitted stdio MCP commands.

### Flags

| Flag | Behavior |
|---|---|
| `--json` | Machine-readable JSON on stdout instead of a formatted table. |
| `--no-upload` | Skip saving the result to your Aevrin dashboard (on by default once logged in). Useful in CI, or for a purely local, ephemeral scan. |
| `--fail-on <severity>` | Minimum severity that causes a non-zero exit code. One of `critical`, `high`, `medium`, `low`, `info`. Defaults to `high` (both `critical` and `high` findings fail the build). |
| `--remote` | Scan a local folder on Aevrin's servers instead of this machine, so no Docker or scanner binary is needed locally. Local paths only. |

### Exit codes

| Code | Meaning |
|---|---|
| `0` | Clean: no findings at or above the `--fail-on` threshold. |
| `1` | Findings at or above the `--fail-on` threshold were found. |
| `2` | Couldn't start, authentication, quota, API, target, or flag error. |
| `3` | Incomplete (`ScanStatus.INCOMPLETE`): a stage that had to run did not. This is never treated as a clean pass. |

Results go to stdout; stage progress and diagnostics go to stderr, safe to pipe `--json` output without stage-progress noise mixed in.

Aevrin prints one grade letter and a risk score, then each finding as its own block rather than
a table row, because a table forced every finding down to a title. Stage progress is listed
above it. Run `aevrin scan --help`, or see the full reference for the exact shape:
<https://docs.mcp.aevrin.net/cli>.

## Other commands

```bash
aevrin login / logout           # browser device-code login, credentials in ~/.aevrin
aevrin agent scan               # what the AI coding agents on this machine may do
aevrin agent scan --json        # versioned snapshot; never contains a credential value
aevrin findings triage <id> <status> [--reason ...]
aevrin mcp-server               # local stdio MCP server with one tool, scan_mcp_server
aevrin mcp-header               # print the Authorization header for Aevrin MCP
aevrin registry publish <dir>   # Aevrin administrators only
```

`mcp-server` needs the MCP extra: `pip install "aevrin[mcp]"`, and
`registry publish` the YAML extra: `pip install "aevrin[registry]"`.

Aevrin MCP (`https://api.mcp.aevrin.net/mcp`) needs your Aevrin API key. `mcp-header` prints
`{"Authorization":"Bearer <key>"}` from the key `aevrin login` stored, so Claude Code can read it
without the key being written into its config:

```bash
claude mcp add-json --scope user aevrin '{"type":"http","url":"https://api.mcp.aevrin.net/mcp","headersHelper":"aevrin mcp-header"}'
```

`agent scan` reads configuration only: no agent is started and nothing from a config file is
executed. Nothing leaves the machine without `--upload`. Full reference:
<https://mcp.aevrin.net/docs/cli>.

## Development

```bash
uv sync
uv run pytest tests -v
uv run ruff check .
uv run mypy aevrin_cli
```
