# mitre-mcp: MITRE ATT&CK MCP Server
[](https://registry.modelcontextprotocol.io)
[](https://pypi.org/project/mitre-mcp/)
[](https://pypi.org/project/mitre-mcp/)
[](https://github.com/montimage/mitre-mcp/actions/workflows/test.yml)
[](LICENSE)
[](https://github.com/psf/black)
[](https://github.com/pre-commit/pre-commit)
Production-ready Model Context Protocol (MCP) server that exposes the [MITRE ATT&CK®](https://attack.mitre.org/) framework to LLMs, AI assistants, and automation workflows. Built with the official MCP Python SDK and mitreattack-python library for secure, high-performance access to adversary tactics, techniques, groups, software, and mitigations.
**Available in the [MCP Registry](https://registry.modelcontextprotocol.io)** (search for `io.github.luongnv89/mitre-mcp`).
## Highlights
- **LLM-native experience** – Seamless integration with Claude, Windsurf, Cursor, and any MCP-compatible client
- **Secure-by-default** – Validated inputs, TLS verification, disk-space checks, and structured error handling
- **High performance** – O(1) technique lookups using pre-built indices (80-95% faster than scanning)
- **Flexible deployment** – stdio for local clients or HTTP server for web-based integrations
## Table of Contents
- [Features](#features)
- [Available MCP Tools](#available-mcp-tools)
- [Quick Start](#quick-start)
- [Web Frontend](#web-frontend)
- [Documentation](#documentation)
- [Configuration](#configuration)
- [Performance](#performance)
- [Programmatic API](#programmatic-api)
- [Development](#development)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [License](#license)
## Features
- **Comprehensive MITRE ATT&CK Coverage** - All techniques, tactics, groups, software, and mitigations
- **Multi-Domain Support** - Enterprise, Mobile, and ICS ATT&CK domains
- **Intelligent Caching** - Atomic, per-user caching with conditional refreshes, stale-serve with background refresh, and configurable expiry (default: 14 days)
- **Fast Startup** - Enterprise loads eagerly; mobile and ICS domains lazy-load on first use
- **Performance Optimized** - O(1) lookups using pre-built indices (80-95% faster)
- **Dual Transport Modes** - stdio for local clients, HTTP for web integrations
- **CORS-Enabled HTTP Server** - Async notifications and cross-origin request support
- **Comprehensive Testing** - pytest suite with an enforced coverage gate
- **Pre-commit Quality Checks** - Automated formatting, linting, type checking, and security scanning
- **Input Validation** - Secure-by-default with validated inputs and sanitized responses
- **Programmatic API** - Python and Node.js clients (see [API-INTEGRATION.md](API-INTEGRATION.md))
## Available MCP Tools
| Tool Name | Description |
| ---------------------------------------- | -------------------------------------------------------- |
| `get_techniques` | List all techniques with filtering options |
| `get_technique_by_id` | Look up specific technique by ID (e.g., T1055) |
| `get_techniques_by_tactic` | Get techniques for a specific tactic (e.g., persistence) |
| `get_tactics` | List all tactical categories |
| `get_groups` | List all threat actor groups |
| `get_techniques_used_by_group` | Get techniques used by a specific group (e.g., APT29) |
| `get_software` | List malware and tools with filtering |
| `get_mitigations` | List all security mitigations |
| `get_techniques_mitigated_by_mitigation` | Get techniques addressed by a specific mitigation |
All list and relationship tools accept `limit`/`offset` paging parameters
(default page size 20, maximum 200 — see `MITRE_DEFAULT_PAGE_SIZE` and
`MITRE_MAX_PAGE_SIZE` in `CONTRIBUTING.md`) and return a `pagination`
block (`total`, `offset`, `limit`, `has_more`).
## Quick Start
### Installation
1. **Create and activate a virtual environment:**
```bash
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate.bat
```
2. **Install from PyPI:**
```bash
pip install mitre-mcp
```
3. **Verify installation:**
```bash
mitre-mcp --help
```
### HTTP Mode (Recommended)
**Start the server:**
```bash
mitre-mcp --http
```
**Expected output:**
```
2025-11-17 22:40:10,991 - mitre_mcp.mitre_mcp_server - INFO - Starting MITRE ATT&CK MCP Server (HTTP mode on localhost:8000)
======================================================================
MITRE ATT&CK MCP Server is ready (Streamable HTTP mode)
Server URL: http://localhost:8000
MCP Endpoint: http://localhost:8000/mcp
Add this to your MCP client configuration:
{
"mcpServers": {
"mitreattack": {
"url": "http://localhost:8000/mcp"
}
}
}
======================================================================
```
**Configure your MCP client:**
Add this JSON to your client's configuration file:
```json
{
"mcpServers": {
"mitreattack": {
"url": "http://localhost:8000/mcp"
}
}
}
```
**Configuration file locations:**
- **macOS (Claude Desktop)**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows (Claude Desktop)**: `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux (Claude Desktop)**: `~/.config/Claude/claude_desktop_config.json`
- **VSCode**: Configure in your MCP extension settings
**Custom host and port:**
```bash
mitre-mcp --http --host 0.0.0.0 --port 8080
```
Then use `http://your-server-ip:8080/mcp` in your client configuration.
> **Security — a non-loopback bind is unauthenticated by default.**
> Binding `--host 0.0.0.0` (or any non-loopback address) exposes the MCP
> endpoint to the whole network: the data is public, but the endpoint is
> an open CPU and memory amplifier. Either set `MITRE_HTTP_AUTH_TOKEN`
> so every request must carry `Authorization: Bearer `:
>
> ```bash
> MITRE_HTTP_AUTH_TOKEN=$(openssl rand -hex 32) mitre-mcp --http --host 0.0.0.0 --port 8080
> ```
>
> or place an authenticating reverse proxy in front of a loopback-only
> server — nginx example (TLS + basic auth → `127.0.0.1:8000`):
>
> ```nginx
> server {
> listen 443 ssl;
> server_name mcp.example.com;
> ssl_certificate /etc/nginx/certs/mcp.example.com.pem;
> ssl_certificate_key /etc/nginx/certs/mcp.example.com.key;
>
> location / {
> auth_basic "mitre-mcp";
> auth_basic_user_file /etc/nginx/.htpasswd;
> proxy_pass http://127.0.0.1:8000;
> proxy_set_header Host $host;
> }
> }
> ```
>
> The server logs a warning at startup whenever it binds a non-loopback
> host without `MITRE_HTTP_AUTH_TOKEN` set.
**Why HTTP mode?**
- Multiple clients can connect simultaneously
- Better concurrency and async support
- Easier debugging with HTTP tools
- CORS support for web-based clients
- No path configuration needed
### stdio Mode (Alternative)
For local-only clients that require stdio transport:
```bash
mitre-mcp
```
**Client configuration:**
```json
{
"mcpServers": {
"mitreattack": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["-m", "mitre_mcp.mitre_mcp_server"]
}
}
}
```
**Note:** Use absolute paths. HTTP mode is recommended for most use cases.
### Force Data Download
Force a fresh download of MITRE ATT&CK data:
```bash
mitre-mcp --http --force-download
```
### Example Screenshots
**VSCode Configuration:**

**Tool Invocation:**

**Results:**

## Web Frontend
A React chat UI lives in `frontend/`. A hosted copy is at
. That public HTTPS page can call
**cloud** LLM providers (Gemini, OpenRouter). It **cannot** reach anything
on this machine — `mitre-mcp` on `localhost:8000`, Ollama, LM Studio, or
any other loopback endpoint. The browser blocks public sites from the
loopback address space (`net::ERR_SSL_PROTOCOL_ERROR` if it upgrades the
MCP URL to `https://localhost:8000/mcp`, CORS / private-network errors for
`http://localhost:…/v1/models`).
Use the local UI whenever the MCP server or the LLM runs on your computer.
### Local setup (MCP server + chat UI)
Two terminals, from a clone of this repository.
**1. Install and start the MCP server** (Python >= 3.11):
```bash
uv sync --locked --extra dev
source .venv/bin/activate
mitre-mcp --http
```
Wait for `MCP Endpoint: http://localhost:8000/mcp`. The first start
downloads ATT&CK data into `~/.cache/mitre-mcp`.
**2. Start the chat UI** (Node 24):
```bash
cd frontend
npm ci
npm run dev
```
Open **http://localhost:5173/** — not the GitHub Pages URL.
**3. Settings** (gear in the chat header):
| Setting | Local value |
| ------- | ----------- |
| MCP host / port | `localhost` / `8000` (dev proxies `/mcp` to the server) |
| LLM provider | Ollama, Gemini, OpenRouter, or **OpenAI-compatible** |
For a local OpenAI-compatible server (LM Studio, llama.cpp, vLLM, …):
- Provider: **OpenAI-compatible**
- Endpoint URL: `http://localhost:/v1` (example: `http://localhost:20128/v1`)
- Model: an id the endpoint lists at `/v1/models`
- API key: leave empty unless that server requires one
The endpoint must allow CORS from `http://localhost:5173`. If Ollama is
not running, do not leave Ollama selected — the default probe hits
`localhost:11434` and Vite logs `http proxy error: /api/tags`.
**For more details**, see [frontend/README.md](frontend/README.md).
## Documentation
We provide three comprehensive guides tailored to different use cases:
### 1. Beginner's Guide
**[Beginner-Playbook.md](Beginner-Playbook.md)** - For those new to MITRE ATT&CK or cybersecurity
**Ideal for:**
- Non-technical users
- Security awareness training
- Basic threat intelligence
- General cybersecurity education
### 2. Advanced Playbook
**[Playbook.md](Playbook.md)** - For security professionals using MCP clients
**Ideal for:**
- Security analysts
- Threat hunters
- Incident responders
- Security engineers
Includes 10 ready-to-use scenarios:
- Threat Intelligence
- Detection Engineering
- Threat Hunting
- Red Teaming
- Security Assessment
- Incident Response
- Security Operations
- Security Training
- Vendor Evaluation
- Risk Management
### 3. API Integration Guide
**[API-INTEGRATION.md](API-INTEGRATION.md)** - For developers building automation and custom integrations
**Ideal for:**
- Backend developers
- Automation engineers
- Data pipeline developers
- Custom tooling projects
Includes:
- Complete Python and Node.js client implementations
- Protocol requirements and examples
- Testing and debugging tools
- Common integration patterns
## Configuration
### Environment Variables
Set before starting `mitre-mcp` to customize behavior:
| Variable | Default | Purpose |
| ----------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------ |
| `MITRE_ENTERPRISE_URL`, `MITRE_MOBILE_URL`, `MITRE_ICS_URL` | Official MITRE CTI GitHub URLs | Override ATT&CK bundle locations or point to internal mirror |
| `MITRE_DATA_DIR` | `~/.cache/mitre-mcp` | Store cached bundles in custom directory |
| `MITRE_DOWNLOAD_TIMEOUT` | `120` | HTTP timeout in seconds for bundle downloads |
| `MITRE_CACHE_EXPIRY_DAYS` | `14` | Maximum age before cached data is refreshed |
| `MITRE_REQUIRED_SPACE_MB` | `200` | Disk space threshold checked before downloading |
| `MITRE_DEFAULT_PAGE_SIZE` / `MITRE_MAX_PAGE_SIZE` | `20` / `200` | Default and maximum records returned by list tools |
| `MITRE_MAX_DESC_LENGTH` | `500` | Trimmed description length in responses |
| `MITRE_LOG_LEVEL` | `INFO` | Logging verbosity (DEBUG, INFO, WARNING, etc.) |
| `MITRE_CORS_ORIGINS` | localhost origins | CORS allowed origins for HTTP mode (comma-separated list; `*` is an explicit opt-in) |
| `MITRE_HTTP_AUTH_TOKEN` | unset (no auth) | Bearer token required on every HTTP request when set; recommended for non-loopback binds |
To let a hosted UI (e.g. the Netlify deployment) call the server cross-origin, set `MITRE_CORS_ORIGINS` to its origin, e.g. `MITRE_CORS_ORIGINS="https://mitre-mcp.netlify.app,http://localhost:5173"`. Credentials are never allowed in any CORS configuration.
### Data Caching
The server automatically caches MITRE ATT&CK data to improve performance:
1. On first run, downloads and stores data in the per-user cache directory
(`$XDG_CACHE_HOME/mitre-mcp`, or `~/.cache/mitre-mcp` by default)
2. On subsequent runs, uses cached data if less than 14 days old
3. Automatically refreshes data older than 14 days, using conditional
requests — a `304 Not Modified` answer reuses the cached bundles.
Expired-but-present data is served immediately while the refresh runs in
the background; startup never blocks on it and a failed refresh keeps
the existing cache.
4. Cache files are written atomically (temp file + rename), so a failed
download never corrupts a good cache
5. Only the enterprise domain is parsed at startup; the mobile and ICS
bundles are lazy-loaded on first use, so cold starts stay fast when they
are never queried
6. Use `--force-download` to force fresh download
## Performance
| Scenario | Improvement | Notes |
| --------------------------- | ----------------- | -------------------------------------------------------------- |
| Enterprise technique lookup | **80-95% faster** | Pre-built O(1) indices for groups, mitigations, and techniques |
| ATT&CK data downloads | **20-40% faster** | HTTP connection pooling with TLS session reuse |
| Warm cache startup | **<2s** | Cached bundles reused for instant LLM queries |
Benchmarks: macOS 14 / Apple M3 Pro with Python 3.11. Use `MITRE_LOG_LEVEL=DEBUG` for timing logs.
## Programmatic API
For automation, custom integrations, and batch processing, see **[API-INTEGRATION.md](API-INTEGRATION.md)**.
**Quick example (Python):**
```python
from clients.python.mini_mcp_client import MitreMCPClient
async def main():
client = MitreMCPClient(host="localhost", port=8000)
# Get all tactics
tactics = await client.call_tool("get_tactics", {"domain": "enterprise-attack"})
# Get techniques for a group
techniques = await client.call_tool(
"get_techniques_used_by_group", {"group_name": "APT29", "domain": "enterprise-attack"}
)
```
**Available clients:**
- **Python**: `clients/python/mini-mcp-client.py` with full CLI
- **Node.js**: `clients/nodejs/mini-mcp-client.js` with full CLI
See [API-INTEGRATION.md](API-INTEGRATION.md) for complete documentation.
## Development
### Clone and Install
```bash
git clone https://github.com/montimage/mitre-mcp.git
cd mitre-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```
### Install Pre-commit Hooks
```bash
pre-commit install
```
This sets up automatic code quality checks before each commit.
### Run Tests
```bash
pytest # Full test suite with coverage
pre-commit run --all-files # All quality checks
```
### Code Quality Tools
**Formatting:**
- **black** - Python code formatter
- **isort** - Import organizer
- **prettier** - YAML/JSON/Markdown formatter
**Linting & Type Checking:**
- **flake8** - Python linter
- **mypy** - Static type checker
- **pydocstyle** - Docstring checker
**Security:**
- **bandit** - Security vulnerability scanner
- **File validators** - YAML, JSON, TOML, private key detection
**Testing:**
- **pytest** - test suite with coverage gate before commit
- **Installation test** - Package verification
- **Import verification** - Module importability
- **CLI test** - Entry point validation
## Troubleshooting
**Download fails with "Insufficient disk space"**
- Free at least 200 MB in the data directory or set `MITRE_DATA_DIR=/path/to/storage`
**Data never updates**
- Cached bundles refresh automatically after 14 days
- Force refresh: `mitre-mcp --force-download` or delete `~/.cache/mitre-mcp`
**Tool calls return errors**
- Ensure technique IDs follow `T####` or `T####.###` format
- Keep names/tactics under 100 characters
**MCP client cannot discover server**
- Verify client configuration points to correct Python path
- Test manually: run `mitre-mcp` and verify server starts
- For HTTP mode: ensure `url` field is set correctly
**Chat UI: `POST https://localhost:8000/mcp net::ERR_SSL_PROTOCOL_ERROR`**
- The GitHub Pages UI is HTTPS, so it rewrites `localhost` to
`https://localhost:8000`. `mitre-mcp --http` has no TLS. Open
http://localhost:5173 instead (see [Web Frontend](#web-frontend)).
**Chat UI: CORS / “loopback address space” when calling a local LLM**
- Same cause: a public origin cannot fetch `http://localhost:…`. Run the
frontend locally and point the OpenAI-compatible provider at
`http://localhost:/v1`.
**Module not found: mcp.server.fastmcp**
- Reinstall the pinned MCP SDK: `pip install "mcp>=1.28.1,<2"` (or `mcp[cli]>=1.28.1,<2` if you also want the CLI extra) in your virtual environment — the `fastmcp` distribution does not provide `mcp.server.fastmcp`; the package's declared pin does
## FAQ
**Does mitre-mcp work offline?**
- Yes. Once bundles are cached, the server works offline until cache expires.
**Which Python versions are supported?**
- Python 3.11 through 3.14 (see `pyproject.toml`).
**How often is data refreshed?**
- By default every 24 hours. Adjust `MITRE_CACHE_EXPIRY_DAYS` or use `--force-download`.
**Is HTTP mode safe for production?**
- HTTP mode serves on localhost:8000 by default. Use firewall or reverse proxy if exposing externally.
## License
MIT License - See [LICENSE](LICENSE) file for details.
## About Montimage
`mitre-mcp` is developed and maintained by [Montimage](https://www.montimage.eu), a cybersecurity company specializing in network monitoring, security analysis, and AI-driven threat detection solutions. We develop innovative tools that help organizations protect their digital assets and ensure network security.
For questions or support: [luong.nguyen@montimage.eu](mailto:luong.nguyen@montimage.com)