Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Pathhound

БесплатноНе проверен

An MCP server that enables LLMs to query and reason over Active Directory attack graphs collected by BloodHound, providing attack paths, blast radius analysis,

GitHubEmbed

Описание

An MCP server that enables LLMs to query and reason over Active Directory attack graphs collected by BloodHound, providing attack paths, blast radius analysis, choke points, and defender remediation advice.

README

An MCP (Model Context Protocol) server that lets an LLM reason over an Active Directory attack graph already collected by BloodHound — shortest paths to Tier 0, blast radius from a principal, the highest-leverage choke points to remediate, and defender-facing remediation text — with every action scoped to an authorized engagement and logged.

Authorized penetration-testing use only. This server never touches a live domain, never collects data, and never runs attacks. Collection is done separately (SharpHound / bloodhound-python); this tool only reads and reasons over the resulting graph in Neo4j. See SECURITY.md for the full intended-use boundary.

What it does

  • Turns a collected graph into explainable answers. Ask "what are the shortest paths to Domain Admins," "if I own this account what becomes reachable," or "which edges should we fix first" and get structured results.
  • Read-only and scoped by design. It refuses to start without an engagement scope, refuses to query domains outside that scope, rejects write/destructive Cypher, and appends every call to an audit log.
  • Defender-facing output. explain_edge and remediation_for_path produce report-ready remediation, not exploit commands.

Tools

Tool What it returns
list_domains() Domains/forests in the graph, with node counts and an in-scope flag.
run_cypher(query, params) Rows from a read-only Cypher query. Write clauses are rejected unless allow_writes is set; destructive/external ops are always refused. Results are row-capped with a truncation flag.
shortest_paths_to_tier0(start, max_paths) Shortest attack paths to Tier 0 / high-value targets — from start (an in-scope principal) or from every owned principal. Each path is an ordered list of start —[edge]→ end hops.
reachable_from(principal, max_hops) Blast radius from a principal, summarized by node type, highlighting any Tier 0 reachability.
find_choke_points(top_n) The edges appearing in the most distinct shortest paths to Tier 0, each with the number of paths removing it would break.
explain_edge(edge_type) Plain-language reason a BloodHound edge (e.g. GenericAll, AddKeyCredentialLink, DCSync) is abusable, the technique name, a defender remediation, and reference pointers.
remediation_for_path(path_id_or_cypher) For a path (given as a read-only Cypher query returning a path p), the specific ACE / delegation / membership change that breaks each hop, phrased for a report.
engagement_summary() Headline counts for reporting: principals, owned, high-value, distinct paths to Tier 0, and the top choke points.

Resources

Resource Contents
pathhound://engagement-scope The active scope (engagement id, authorization reference, allowed domains, write flag) and the Neo4j target with the password masked.
pathhound://cypher-library A curated, versioned set of named read-only Cypher queries (Kerberoastable, unconstrained delegation, AS-REP roastable, paths to Domain Admins, ACL abuse from a principal, …), each validated read-only on load.

Optional write tools (off by default)

Two tools — mark_owned(principal, confirm) and set_high_value(principal, confirm) — set BloodHound's owned / Tier 0 markers (and nothing else) so the path tools treat those nodes accordingly. They only exist when allow_writes: true is set in scope.yaml; each call also requires an explicit confirm=true, an in-scope principal, and is audited. They never delete or drop. Leave allow_writes: false (the default) for a strictly read-only deployment.

Requirements

  • Python 3.11+
  • A BloodHound CE Neo4j instance reachable over Bolt (the graph is collected and ingested separately — see the quickstart below)

Install

# With uv (preferred):
uv venv && uv pip install -e ".[dev]"

# Or with pip:
python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt && pip install -e .

Configure

Two pieces of configuration: the engagement scope (a file) and the Neo4j connection (environment variables — credentials are never hardcoded).

1. Engagement scope — copy the example and edit it:

cp scope.example.yaml scope.yaml
# scope.yaml
engagement_id: "ENG-0001"                      # names the audit log file
authorization_ref: "SoW-2026-ACME-001 / JIRA-1234"
allowed_domains:                               # only these may be queried
  - "CORP.LOCAL"
  - "CHILD.CORP.LOCAL"
allow_writes: false                            # keep false unless you need the write-flag tools
max_rows: 500                                  # run_cypher row cap

The server refuses to start if scope.yaml is missing or allowed_domains is empty — this is intentional; there are no unscoped queries. Domain names are matched case-insensitively against BloodHound's uppercase FQDNs.

2. Neo4j connection — via environment variables (or a .env; see .env.example):

export NEO4J_URI="bolt://127.0.0.1:7687"
export NEO4J_USER="neo4j"
export NEO4J_PASSWORD="…"
export NEO4J_DATABASE="neo4j"        # optional, defaults to neo4j
# export PATHHOUND_SCOPE="/abs/path/scope.yaml"   # optional; defaults to ./scope.yaml

Run

As a standalone stdio MCP server:

pathhound-mcp          # or:  python -m pathhound_mcp.server

Register with an MCP client

Point your client at the console script (use the absolute path from your venv, e.g. /path/to/pathhound-mcp/.venv/bin/pathhound-mcp) and pass the connection + scope through its environment. Example (Claude Desktop claude_desktop_config.json):

{
  "mcpServers": {
    "pathhound": {
      "command": "/path/to/pathhound-mcp/.venv/bin/pathhound-mcp",
      "env": {
        "NEO4J_URI": "bolt://127.0.0.1:7687",
        "NEO4J_USER": "neo4j",
        "NEO4J_PASSWORD": "…",
        "PATHHOUND_SCOPE": "/path/to/pathhound-mcp/scope.yaml"
      }
    }
  }
}

Example questions to ask the LLM

Once connected, an operator can ask things like:

  • "List the domains in the graph and how big each is."list_domains
  • "Which accounts are Kerberoastable?"run_cypher with the kerberoastable_users library query
  • "Show the shortest attack paths to Tier 0."shortest_paths_to_tier0
  • "If I compromise [email protected], what becomes reachable?"reachable_from
  • "What are the top 10 choke points we should fix first?"find_choke_points
  • "Why is AddKeyCredentialLink dangerous, and how do we fix it?"explain_edge
  • "Give me remediation steps for this attack path."remediation_for_path
  • "Summarize the engagement for the report."engagement_summary

Quickstart: collect into BloodHound, then point this at Neo4j

This server only reads an already-collected graph; collection happens separately and outside this tool.

  1. Collect the domain with SharpHound or bloodhound-python during your authorized engagement. You get a set of JSON files (or a zip) — from a lab like GOAD (GOAD-Light ~16 GB, full GOAD ~32 GB) or a real engagement.

  2. Stand up BloodHound CE and ingest the data. The official compose stack runs Neo4j (Bolt on 127.0.0.1:7687), Postgres, and the BloodHound UI on :8080:

    docker compose -f /path/to/docker-compose.yml up -d
    # open http://localhost:8080, log in, and upload the collection zip
    # (Administration → File Ingest). Wait for ingest + post-processing.
    

    If the Neo4j volume is already ingested, you can start just the graph: docker compose -f /path/to/docker-compose.yml up -d graph-db.

  3. Point pathhound-mcp at that Neo4j (see Configure) and run it. Your allowed_domains in scope.yaml should match the domains in the collection (e.g. CORP.LOCAL).

BloodHound schema compatibility

Newer BloodHound CE tags Tier 0 with the Tag_Tier_Zero node label and owned principals with Tag_Owned, while older versions used the highvalue / owned properties (and CE also sets system_tags: admin_tier_0). pathhound recognizes all of these, so Tier 0 / owned reasoning works across versions.

Tests

pytest        # unit tests — guardrails, scope, audit, Cypher guard, tool logic

The suite is fully database-free: the read-only guardrail, scope enforcement, audit logging, row-capping, and path/reporting logic are all exercised against stubs, so pytest runs in a fraction of a second with no Neo4j. (The tools have also been validated end-to-end against a real BloodHound CE graph.)

Project layout

src/pathhound_mcp/
├── server.py          # FastMCP app: tool/resource registration + startup guard
├── config.py          # loads/validates scope.yaml (pydantic); Neo4j from env
├── guardrails.py      # read-only Cypher guard + scope enforcement
├── audit.py           # append-only JSONL audit logger (@audited decorator)
├── graph.py           # Neo4j connection + read helpers (the only DB access)
├── schema.py          # attack-edge set + Tier 0 / owned predicates
├── models.py          # pydantic result models
├── cypher_library.json / edge_library.json   # curated read-only queries + edge KB
└── tools/             # inventory, query, paths, reporting, edges

audit/, scope.yaml, and .env are gitignored — treat the audit log and the collected graph as engagement-sensitive.

Safety model

See SECURITY.md for the intended-use boundary and the guarantees: scope-at-startup, read-only by default, scope enforcement, append-only audit log, and no live-domain capability.

License

MIT — see LICENSE.

from github.com/iabdullah215/pathhound-mcp

Установка Pathhound

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/iabdullah215/pathhound-mcp

FAQ

Pathhound MCP бесплатный?

Да, Pathhound MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Pathhound?

Нет, Pathhound работает без API-ключей и переменных окружения.

Pathhound — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Pathhound в Claude Desktop, Claude Code или Cursor?

Открой Pathhound на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Pathhound with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development