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,
Описание
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_edgeandremediation_for_pathproduce 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_cypherwith thekerberoastable_userslibrary 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
AddKeyCredentialLinkdangerous, 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.
Collect the domain with SharpHound or
bloodhound-pythonduring 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.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.Point pathhound-mcp at that Neo4j (see Configure) and run it. Your
allowed_domainsinscope.yamlshould 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.
Установка Pathhound
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/iabdullah215/pathhound-mcpFAQ
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
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Pathhound with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
