Skip to content
Conduit

mcp server

artblood

A fast and smart analyzer for BloodHound data with TUI and MCP.

art3x/artbloodcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 25, 2026

ArtBlood

ArtBlood is a fast, offline command-line analyzer for BloodHound data. It imports SharpHound JSON files, directories, or ZIP archives into a local indexed cache and provides search, pathfinding, security-focused reports, exports, and an interactive terminal interface without requiring Neo4j or a running BloodHound server.

ArtBlood also has an MCP server on board that enables AI agents to efficiently retrieve information about Active Directory.

[!IMPORTANT] ArtBlood is intended for authorized security assessment, defensive analysis, and lab use. BloodHound collections and ArtBlood reports can contain highly sensitive identity and infrastructure data. Keep them out of source control and protect them according to your organization's data-handling requirements.

Highlights

  • Import one or more SharpHound JSON directories or ZIP archives.
  • Inspect nodes, relationships, properties, and shortest attack paths.
  • Find paths from owned principals to tier-zero targets.
  • Report dangerous ACLs, Kerberoastable and AS-REP roastable users, sessions, local administrators, and AD CS ESC findings.
  • Explore results in a keyboard- and mouse-driven terminal UI.
  • Use AI to query data via MCP
  • Run a native graph query DSL or a practical subset of Cypher.
  • Generate Markdown assessment reports and BloodHound-style text reports.
  • Merge new collections into an existing cache with --append.
  • Search objects by name, SID, distinguished name, or object ID.
  • Compare caches and export table, JSON, JSONL, CSV, Markdown, DOT, GraphML, or OpenGraph data where supported.
  • Redact names or other identifying data from supported reports and exports.

Build and install

Download or clone the repository, then build the workspace:

cd ArtBlood
cargo build --workspace

Build an optimized binary:

cargo build --release --workspace

The resulting executable is:

  • Linux/macOS: target/release/abh
  • Windows: target\release\abh.exe (not tested)

You can also install it into Cargo's binary directory:

cargo install --path crates/abh-cli

Quick start

Ingest SharpHound data into per-user cache at ~/.abh/cache:

abh ingest 20260725153725_bloodhound.zip

Inspect and analyze the imported graph:

abh doctor
abh stats --by-kind --by-edge-kind
abh search alice
abh path --from "ALICE@CORP.LOCAL" --to tier0
abh owned-to-tier0
abh dangerous-acls --format markdown
abh ui

Most commands use ~/.abh/cache when no cache path is provided. This gives every invocation by the same user one shared cache, regardless of the current working directory. Run abh --help or abh <command> --help for the complete option set.

Importing data

Import multiple inputs in one operation:

abh ingest first.zip second.zip --progress

Add new collections to an existing cache:

abh ingest latest.zip --append

Replace an existing cache without an interactive prompt:

abh ingest latest.zip --force

If the output cache already exists and neither --append nor --force is used, ArtBlood asks whether to append, rewrite, or quit when attached to an interactive terminal. Non-interactive callers must choose --append or --force explicitly. Pass --output <path> during ingestion, or a cache argument to commands that accept one, to override the shared cache.

Codex and MCP

ArtBlood includes a local STDIO MCP server so Codex can inspect and update one cache through structured tools. Register the default cache:

codex mcp add artblood -- abh mcp

Or bind the server to an explicit cache:

codex mcp add artblood -- abh mcp --cache /absolute/path/to/corp-cache

The equivalent user or trusted-project config.toml entry is:

[mcp_servers.artblood]
command = "abh"
args = ["mcp", "--cache", "/absolute/path/to/corp-cache"]

Run codex mcp list to verify the registration. Inside Codex, use /mcp to inspect the connected server and its tools.

The server exposes graph_stats, search_nodes, get_node, get_edge, query_graph, shortest_paths, reload_cache, and ingest. For example, ask Codex to search for a principal, run a native DSL or Cypher query, explain an attack path, or ingest several SharpHound directories with an explicit create, append, or replace mode. If another abh process changes the cache, ask Codex to call reload_cache.

Commands

CommandPurpose
ingestImport BloodHound JSON/ZIP data into an indexed cache
statsShow graph totals and optional node/edge breakdowns
searchFind objects by identity or name
nodeShow node details, properties, and relationships
edgeShow relationship details and properties
pathFind shortest paths between objects or selectors
owned-to-tier0Find attack paths from owned objects to tier zero
dangerous-aclsList high-risk ACL relationships
kerberoastList enabled Kerberoastable users
asrep-roastList enabled AS-REP roastable users
sessionsList and filter user-session relationships
local-adminsList and filter local-administrator relationships
cert-escReport Active Directory Certificate Services ESC findings
queryRun the native DSL or supported Cypher subset
exportExport graph objects or queried paths
diffCompare two ArtBlood caches
reportGenerate a Markdown assessment report
bloodGenerate a BloodHound-style plain-text report
mcpServe one cache to Codex and other local MCP clients
uiOpen the interactive terminal interface
doctorValidate cache structure and integrity

Querying

The native DSL provides concise selectors for nodes, relationships, and paths:

abh query 'nodes(kind=User, enabled=true, hasspn=true, limit=25)'
abh query 'nodes(kind=Computer, domaincontroller=true)'
abh query 'nodes(kind in [User,Computer], owned=true)'
abh query 'nodes(kind=User, description~="service account")'
abh query 'nodes(kind=User, logoncount>=10)'
abh query 'edges(kind in [GenericAll, WriteDacl, WriteOwner], limit=50)'
abh query 'edges(kind=MemberOf, from="ALICE@CORP.LOCAL")'
abh query 'path(from=owned(), to=tier0(), edges=attack, max_depth=8, limit=10)'

Native node predicates accept = for case-sensitive exact scalar matching, ~= for a case-insensitive substring match, and in [...] for node or relationship kind lists. The operators >, <, >=, and <= compare typed numbers and finite numeric strings numerically. Property names may refer to built-in identity fields, node flags, or any scalar attribute stored on the object. Path queries accept the all, attack, acl, membership, session, admin, cert, and azure relationship profiles.

tierzero and highvalue are effective classifications: recursive members of privileged groups are included, and Tier Zero principals are considered high value. The interactive object's corresponding detail fields and clickable filters use the same classification.

Domain Controller classification is likewise effective: ArtBlood recognizes the imported flag/property and membership in the built-in Domain Controllers groups, and uses that result consistently in queries, reports, and UI details.

ArtBlood also supports a focused Cypher subset for common graph-analysis tasks:

abh query --format table \
  'MATCH (u:User) WHERE u.enabled = true RETURN u LIMIT 25'

abh query --format table \
  'MATCH (c:Computer) WHERE c.smbsigning = false RETURN c LIMIT 100'

abh query --format table \
  'MATCH (u:User) WHERE u.enabled = true AND (u.hasspn = true OR u.dontreqpreauth = true) RETURN u LIMIT 50'

abh query --format table \
  'MATCH (u:User) WHERE u.description IS NOT NULL RETURN u.name, u.description'

abh query --format table \
  'MATCH (u:User)-[r:MemberOf]->(g:Group) WHERE g.name CONTAINS "DOMAIN ADMINS" RETURN r'

abh query --format table \
  'MATCH p=shortestPath((u:User)-[*1..5]->(g:Group)) WHERE u.name CONTAINS "ALICE" AND g.name CONTAINS "DOMAIN ADMINS" RETURN p LIMIT 5'

abh query --format table \
  'MATCH p=(g:Group)-[r:Owns|WriteDacl|GenericAll]->(c:Computer) WHERE g.name STARTS WITH "DOMAIN ADMINS" RETURN p'

Supported Cypher functionality includes node-kind matching, fixed and variable-length relationships, shortestPath, typed node and relationship properties, IS NULL/IS NOT NULL, parenthesized AND/OR/NOT expressions, property projections, RETURN, and LIMIT. Exact string equality is case-sensitive; CONTAINS, STARTS WITH, and ENDS WITH are case-insensitive.

Interactive-UI custom queries are saved per user in ~/.abh/custom_queries.json. On first launch after upgrading, ArtBlood copies queries from the previous platform config location when the new file does not yet exist.

Reports and exports

Examples:

abh cert-esc --format markdown -o cert-report.md
abh report -o assessment.md --redact names
abh blood -o blood-report.txt
abh diff old.bhx new.bhx --format markdown --redact names
abh export --nodes --edges --format graphml -o graph.graphml
abh export --format opengraph -o graph.json

abh export accepts these formats:

  • table — a human-readable Markdown graph report.
  • json — one JSON document containing nodes and edges arrays.
  • jsonl — one typed node or edge record per line.
  • csv — node rows by default; use --edges for relationship rows.
  • markdown (or md) — a Markdown graph report.
  • dot — Graphviz DOT.
  • graphml — GraphML.
  • opengraph (or open-graph) — BloodHound OpenGraph JSON.

Without --nodes or --edges, graph exports include both, except CSV, which emits nodes because it has a single table schema. CSV rejects --nodes --edges.

Not every output format applies to every command. The command help identifies the accepted options, and ArtBlood reports an error for unsupported combinations.

In the Blood report, potential RBCD configuration findings are limited to computer targets and classified as direct attribute write, broad computer control, or indirect ACL takeover. The classification distinguishes an immediate property-write capability from permissions that require additional ACL or ownership changes.

Interactive terminal UI

Run abh with no subcommand or use ui like:

abh
abh ui

When the Query field is focused, searchable attribute labels in the right-hand object-information column are highlighted. Click a label to insert an exact filter containing that object's current raw value at the query cursor. Native nodes(...) queries receive comma-separated predicates; supported Cypher queries receive a variable-qualified WHERE predicate.

The UI provides clickable query, search, and path fields; autocomplete; pre-built searches; object and relationship details; directory mapping; and report rendering.

Pre-built searches that require graph-derived or alias-aware logic place a pb "Search title" command in the Query field. Re-running that command always executes the same search. Simpler searches expose their complete native query.

  • Use the mouse wheel over a column to scroll it.
  • Use PageUp and PageDown to scroll the center column by one visible page.
  • Press h for in-application help.
  • Press Ctrl+Z to return to the previous view.
  • Press q to quit when no input field is focused.

Development

Run the same core checks used by CI:

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace --locked
cargo build --release --workspace --locked
python scripts/check_sensitive_files.py --all

Workspace layout:

crates/
  abh-schema       Shared graph schema and object/relationship types
  abh-graph        In-memory graph model and indexing
  abh-ingest       SharpHound and OpenGraph ingestion
  abh-cache        Persistent indexed cache format
  abh-algorithms   Pathfinding and graph-analysis algorithms
  abh-query        Native DSL and supported Cypher parser/executor
  abh-output       Output formatters
  abh-cli          The abh command-line and terminal UI

License

ArtBlood is licensed under the GNU General Public License v3.0 only (GPL-3.0-only). See LICENSE.

Generated relationship-help content includes material adapted from BloodHound under the Apache License 2.0. See THIRD_PARTY_NOTICES.md for attribution.

↑↓ navigate openesc close