Skip to main content

A fast Python CLI for MITRE ATT&CK. Designed for coding agents — clean JSON output over stdout, no MCP daemon required.

Project description

mitre-attack-cli

A fast, dependency-light Python CLI for MITRE ATT&CK. Built for coding agents to invoke through the Bash tool: clean JSON on stdout, useful errors on stderr, predictable exit codes. No MCP daemon required.

Why

Coding agents that need MITRE ATT&CK knowledge currently rely on MCP servers (e.g. stoyky/mitre-attack-mcp, MHaggis/mitre-attack-mcp). An MCP brings infrastructure — a long-lived process, a transport, an MCP-aware host — to what is fundamentally a read-only data lookup. This CLI is just a binary on $PATH, easier to install (uvx mitre-attack-cli ...), easier to use in CI or sandboxes, and equally agent-friendly: every command returns parseable JSON.

Quickstart

# One-shot via uvx (no install)
uvx mitre-attack-cli technique get T1059.001

# Or install globally
uv tool install mitre-attack-cli
mitre technique get T1059.001

First invocation downloads the ATT&CK Enterprise STIX bundle (~25–45 MB) into ~/.cache/mitre-attack-cli/. Subsequent calls are local.

Output

Default is compact JSON on stdout. Errors are JSON envelopes on stderr.

$ mitre technique get T1059.001
{"attack_id":"T1059.001","name":"PowerShell","tactics":["execution"],"platforms":["Windows"],"is_subtechnique":true}

$ mitre technique get T9999
# stdout: empty
# stderr:
{"error":"Not found: 'T9999' in enterprise@v19.0.","code":"NOT_FOUND","hint":"Try `mitre search T9999` or `mitre update`."}
# exit code: 3

Three formats:

Flag Behavior
--format json (default) Compact JSON. Single line per object, single array for lists.
--format jsonl Newline-delimited JSON. Best for piping large lists to jq.
--pretty (or --format pretty) Markdown for objects, table for lists. For humans.

Exit codes: 0 success · 2 invalid usage · 3 not found · 4 missing data · 5 network · 1 other.

Subcommands

mitre technique     get | list | subtechniques | parent | groups-using | software-using
                    | mitigations | detections | procedures | tactics
mitre tactic        get | list | techniques
mitre group         get | list | techniques | software | campaigns
mitre software      get | list | groups-using | techniques | campaigns
mitre mitigation    get | list | techniques
mitre campaign      get | list | groups | techniques | software
mitre data-source   get | list | components | techniques
mitre search        <query> [--type … --regex --limit N]
mitre update        [--domain … --all-domains --force]
mitre info          # diagnostic JSON: cache path, active version, etc.

Global flags must precede the subcommand:

--domain {enterprise|mobile|ics}     # default: enterprise
--attack-version v19.0               # default; or MITRE_ATTACK_VERSION env
--data-path PATH                     # pre-downloaded STIX dir/file (or MITRE_ATTACK_DATA_PATH)
--format {json|jsonl|pretty}         # default: json
--pretty                             # human-readable
--fields a,b,c                       # whitelisted field projection
--full                               # all fields
--include-revoked                    # include revoked/deprecated objects
--offline                            # fail rather than download
--quiet                              # suppress stderr progress logs

Examples

# Lookup
mitre --pretty technique get T1059.001
mitre group get APT28                       # alias resolves to G0007

# Relationships
mitre technique groups-using T1059.001
mitre technique mitigations T1059.001
mitre group techniques G0007

# Listings + filtering + field selection
mitre technique list --tactic lateral-movement --platform Windows
mitre --fields attack_id,name --format jsonl technique list

# Search
mitre search "kerberoasting" --limit 5
mitre search '^Power' --regex --type technique

# Diagnostics
mitre info

Data: bring your own or let it download

Three resolution paths, in order:

  1. --data-path PATH (or MITRE_ATTACK_DATA_PATH env). Accepts:
    • A direct file (/path/to/enterprise-attack.json)
    • A flat directory containing enterprise-attack.json
    • A {version}/{domain}-attack.json layout (e.g. ~/cache/v19.0/enterprise-attack.json). This matches common ETL cache layouts, so pre-downloaded bundles are reused without re-downloading.
  2. Local cache at ~/.cache/mitre-attack-cli/{version}/{domain}-attack.json (honors XDG_CACHE_HOME).
  3. Download from https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/{domain}-attack/{domain}-attack-{version}.json unless --offline.

Refresh is explicit via mitre update. The pinned default version is v19.0; override with --attack-version v15.1 or MITRE_ATTACK_VERSION=v15.1. The version is the reproducibility contract — same CLI version + same --attack-version returns the same answers.

Only the domain you request is downloaded. --domain mobile will fetch mobile-attack lazily; enterprise and ics aren't touched.

Performance

Coding agents fire many short-lived mitre ... invocations. Loading the full ATT&CK STIX bundle through stix2 every time would cost ~2.4 s per call. To avoid that, the CLI maintains a compiled snapshot cache next to each STIX file:

~/.cache/mitre-attack-cli/v19.0/
├── enterprise-attack.json          # raw STIX (downloaded on demand)
└── enterprise-attack.cache.msgpack # compiled snapshot — used by every warm run
Run Wall clock What happens
First (cold) ~25–30 s mitreattack-python loads the STIX bundle once, builds a msgpack snapshot with every relationship pre-resolved.
Warm ~150–300 ms mitreattack-python is never imported. The hot path is typer + httpx + msgpack + pure-dict lookups.
Cache invalid ~25–30 s Rebuilt automatically when the STIX file's mtime/size changes, when the CLI version changes, or when you run mitre update --force.

The snapshot uses msgpack — a binary, data-only format. It lives in your own writable cache dir even when the STIX bundle itself comes from --data-path, so a read-only data path remains read-only.

Install

uv tool install mitre-attack-cli         # recommended
pipx install mitre-attack-cli            # alternative
uvx mitre-attack-cli technique get T1059 # no install, one-shot

Development

git clone https://github.com/nitzpo/mitre-attack-cli
cd mitre-attack-cli
uv sync --all-groups
uv run python tests/fixtures/build_tiny_bundle.py   # build test fixture
uv run pytest                                       # 114 tests, ~1s
uv run ruff check . && uv run ruff format --check .

The project uses uv for dependency management, ruff for lint+format, ty for type checking, and pytest for tests. CI runs on Python 3.12 and 3.13 across Ubuntu and macOS.

Architecture

Four layers, each independently testable:

cli/      # Typer commands, global flags, CliContext
└─ output/   # JSON/JSONL/markdown formatters, field projection, error envelope
   └─ domain/  # ranked search, per-kind list/get/filter logic
      └─ repo/   # AttackRepository wrapping mitreattack-python's MitreAttackData
         └─ data/  # path resolution, httpx download with atomic-rename

The data layer is intentionally agnostic about ATT&CK schema specifics so future loaders (D3FEND, CAPEC, Atomic Red Team) can plug in without disturbing the CLI surface.

Differences vs the existing MCPs

  • No daemon, no MCP server, no transport. Just a binary on $PATH.
  • JSON-by-default for agents; --pretty for humans.
  • Lazy per-domain download — only fetches what you ask for, not all three.
  • Pre-downloaded path interop — points at any existing STIX bundle including versioned {version}/{domain}-attack.json layouts.
  • Stable error envelope with documented codes (NOT_FOUND, MISSING_DATA, …) and useful hints in every error.

License

MIT. See LICENSE.

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

mitre_attack_cli-0.2.0.tar.gz (32.1 kB view details)

Uploaded Source

Built Distribution

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

mitre_attack_cli-0.2.0-py3-none-any.whl (47.2 kB view details)

Uploaded Python 3

File details

Details for the file mitre_attack_cli-0.2.0.tar.gz.

File metadata

  • Download URL: mitre_attack_cli-0.2.0.tar.gz
  • Upload date:
  • Size: 32.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mitre_attack_cli-0.2.0.tar.gz
Algorithm Hash digest
SHA256 13e2f015be1e94fef36550fab548aa1a951ef7077553d0fa4f2a4fe1e241a43b
MD5 88b5739ecf88575691cff39fba79ea67
BLAKE2b-256 6e2b035a8642099acf4c6585d6b8c3de918808a621ed76b2b55a8d5c92ba3a6a

See more details on using hashes here.

Provenance

The following attestation bundles were made for mitre_attack_cli-0.2.0.tar.gz:

Publisher: release.yml on nitzpo/mitre-attack-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mitre_attack_cli-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mitre_attack_cli-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6e7789d4c2333f02eb8268d52ec3d218c7c8634c0529c28bc74a18186faac0ed
MD5 b7c8b11782f0474019fea464eed43da6
BLAKE2b-256 fe98940e11abef799c132103d92e65aa0db2e91b24737501bcb3b3c6f824dcf3

See more details on using hashes here.

Provenance

The following attestation bundles were made for mitre_attack_cli-0.2.0-py3-none-any.whl:

Publisher: release.yml on nitzpo/mitre-attack-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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