mcp-hayabusa
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-hayabusascan C:\Windows\System32\winevt\Logs\Security.evtx"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-hayabusa
An MCP server that wraps Hayabusa for EVTX (Windows event log) analysis, exposing scan_evtx and get_hayabusa_rules tools to Claude. It also provides a small detection engineering knowledge base — a curated set of Sigma rules under rules/, browsable as detection:// MCP resources and queryable via analyze_coverage, cross-referenced against MITRE ATT&CK technique data to report coverage — plus suggest_rule to turn an identified gap into a starter rule template, a set of incident response playbooks under playbooks/ (browsable via detection://playbooks and resolvable from an alert name via detection://playbooks/by-alert/{alert_name}), environment-specific knowledge under environment/ (detection://environment/hosts, /services, /baselines) for judging whether a detection is consistent with normal operations, and past investigation notes under investigations/ (detection://investigations, /{case_id}, /by-technique/{tid}).
Setup
Install dependencies:
pip install -r requirements.txtDownload the Hayabusa binary and Sigma rules into
./hayabusa/:python download_hayabusa.pyThis fetches the latest release for your OS/architecture and extracts it to
./hayabusa/(binary at./hayabusa/hayabusa.exeon Windows or./hayabusa/hayabusaelsewhere, plusrules/andrules/config/).Keep the ruleset current (recommended before each scanning session):
./hayabusa/hayabusa.exe update-rules # Windows ./hayabusa/hayabusa update-rules # Linux/macOS(Optional, for the
detection://attack/techniques/{technique_id}resource) Download MITRE ATT&CK technique data into./mappings/attack_techniques.json:python download_attack_data.pyThis fetches the MITRE ATT&CK Enterprise STIX dataset and caches technique name/description/tactics locally. Without it, coverage lookups still work but technique name/description come back
null.
Related MCP server: mcp-hayabusa
Running the server
python server.pyThis starts the MCP server over stdio. Point an MCP client at it, e.g. in Claude Desktop's config:
{
"mcpServers": {
"hayabusa": {
"command": "python",
"args": ["C:\\path\\to\\mcp-hayabusa\\server.py"]
}
}
}Tool: scan_evtx
Scans an EVTX file (or a directory of EVTX files) with Hayabusa and returns detections as structured JSON.
Parameters:
evtx_path(string, required) — path to a.evtxfile or a directory containing themmin_severity(string, optional, default"informational") — minimum severity to include:informational,low,medium,high,criticalrule_filter(string, optional) — case-insensitive substring match against each detection's rule title (e.g."lateral"or"mimikatz"); only matching detections are returned. Hayabusa has no native rule-title filter, so this is applied after the scan.output_format(string, optional, default"summary") —"summary"returns condensed detections (Timestamp,RuleTitle,Level,Computer,Channel,EventID,RecordID);"full"includes the completeDetails/ExtraFieldInfopayload for each detectionmax_results(integer, optional) — caps the number of detections returned, applied afterrule_filter
Returns:
{
"evtx_path": "...",
"min_severity": "...",
"rule_filter": "...",
"output_format": "...",
"total_count": 68,
"count": 42,
"truncated": false,
"detections": [ { "Timestamp": "...", "RuleTitle": "...", "Level": "...", "...": "..." } ]
}total_count is the number of matching detections before max_results is applied; count is the number actually returned; truncated is true if max_results cut off results.
On failure (missing file, missing Hayabusa binary, invalid min_severity/output_format/max_results, scan timeout, or a Hayabusa scan error), it returns {"error": "..."} instead of raising.
Tool: get_hayabusa_rules
Lists available Hayabusa/Sigma detection rules from ./hayabusa/rules/, optionally filtered by keyword. Useful for seeing what detections exist before scanning, or for finding a good rule_filter value for scan_evtx. Hayabusa has no built-in rule-listing command, so this reads and parses the rule YAML files directly.
Parameters:
keyword(string, optional) — case-insensitive substring matched against each rule's title, description, tags, and id. If omitted, all rules are listed (subject tomax_results)max_results(integer, optional, default100) — caps the number of rules returned
Returns:
{
"keyword": "...",
"total_count": 66,
"count": 66,
"truncated": false,
"rules": [
{
"id": "...",
"title": "...",
"level": "...",
"status": "...",
"description": "...",
"logsource": { "product": "windows", "service": "..." },
"tags": ["attack.lateral-movement", "..."],
"file": "hayabusa\\builtin\\System\\Sys_7045_Med_LateralMovement-PSEXEC.yml"
}
]
}total_count is the number of matching rules before max_results is applied; count is the number actually returned; truncated is true if max_results cut off results.
A keyword search checks a raw-text prefilter before parsing each rule's YAML, so it typically runs in ~1-2 seconds. Listing all ~5,000 rules with no keyword takes several seconds longer since every rule file must be parsed.
On failure (missing rules directory or invalid max_results), it returns {"error": "..."} instead of raising.
Resources: detection://...
These read our own curated Sigma rules in ./rules/ — a small, hand-picked set covering things like LSASS credential access, Kerberoasting, DCSync, and Pass-the-Hash — as opposed to get_hayabusa_rules, which lists Hayabusa's full bundled ruleset.
detection://rules
Lists every rule in ./rules/.
{
"count": 8,
"rules": [
{
"name": "lsass_access_sysmon",
"id": "c81db55e-5f41-49ab-b5ef-b5241d67e3d8",
"title": "Suspicious Process Access to LSASS Memory",
"level": "high",
"status": "stable",
"description": "Detects a process opening a handle to lsass.exe with an access mask commonly...",
"logsource": { "category": "process_access", "product": "windows" },
"tags": ["attack.credential-access", "attack.t1003.001", "attack.s0002"],
"file": "lsass_access_sysmon.yml"
}
]
}detection://rules/{rule_name}
Returns one rule's full parsed content plus its raw YAML. rule_name is the filename stem (the name field from detection://rules), e.g. detection://rules/kerberoasting_4769.
{
"name": "kerberoasting_4769",
"file": "kerberoasting_4769.yml",
"rule": { "title": "...", "id": "...", "detection": { "...": "..." } },
"raw": "title: Kerberoasting - Suspicious Service Ticket Request...\n..."
}Returns {"error": "..."} for an unknown or invalid rule name.
detection://rules/by-technique/{technique_id}
Lists rules tagged with a given ATT&CK technique ID via attack.tNNNN[.NNN] Sigma tags. technique_id is case-insensitive and works with or without the leading T (T1003.001, t1003.001, 1003.001 are equivalent).
{
"technique_id": "T1003.001",
"count": 2,
"rules": [ { "name": "lsass_access_sysmon", "...": "..." }, { "name": "lsass_dump_comsvcs", "...": "..." } ]
}detection://attack/techniques/{technique_id}
Combines MITRE ATT&CK technique metadata with our rule coverage for that technique. Technique name/description/tactics come from the local cache built by download_attack_data.py; rule coverage is always computed live from ./rules/, independent of whether that cache exists.
{
"technique_id": "T1003.001",
"coverage": "covered",
"rules": [ { "name": "lsass_access_sysmon", "...": "..." }, { "name": "lsass_dump_comsvcs", "...": "..." } ],
"name": "OS Credential Dumping: LSASS Memory",
"description": "Adversaries may attempt to access credential material stored in the process memory of the Local Security Authority Subsystem Service (LSASS)...",
"tactics": ["credential-access"],
"url": "https://attack.mitre.org/techniques/T1003/001"
}coverage is one of:
"covered"— at least one matching rule hasstatus: stable"partial"— matching rules exist, but all are stillexperimental/unstable"gap"— no rules reference this technique at all
If the ATT&CK cache hasn't been downloaded, or the technique ID isn't found in it, name/description/tactics/url come back null and a note field explains why — coverage/rules are still populated either way.
detection://playbooks
Lists all incident response playbooks in ./playbooks/ — a small curated set covering the alert families our ./rules/ currently detect (credential theft, pass-the-hash, password spraying).
{
"count": 3,
"playbooks": [
{
"id": "credential-theft",
"name": "Credential Theft Response",
"severity": "critical",
"description": "Response procedure for detections indicating credential material was...",
"techniques": ["T1003.001", "T1003.006", "T1218.011", "T1558.003", "T1558.004"],
"triggers": ["LSASS", "DCSync", "Kerberoast", "AS-REP", "comsvcs", "..."],
"file": "credential-theft.yml"
}
]
}detection://playbooks/{playbook_name}
Returns one playbook's full parsed content plus its raw YAML. playbook_name is the filename stem (the id/file from detection://playbooks), e.g. detection://playbooks/pass-the-hash. Each playbook has triage/containment/eradication/recovery phases, each a list of concrete steps.
{
"name": "pass-the-hash",
"file": "pass-the-hash.yml",
"playbook": {
"id": "pass-the-hash",
"name": "Pass-the-Hash Lateral Movement Response",
"severity": "high",
"techniques": ["T1550.002", "T1021.002"],
"phases": {
"triage": ["Identify the account, source workstation/IP, and target host from the logon event (4624 Type 3, AuthenticationPackageName NTLM).", "..."],
"containment": ["..."],
"eradication": ["..."],
"recovery": ["..."]
},
"references": ["https://attack.mitre.org/techniques/T1550/002/"]
},
"raw": "id: pass-the-hash\nname: Pass-the-Hash Lateral Movement Response\n..."
}Returns {"error": "..."} for an unknown or invalid playbook name.
detection://playbooks/by-alert/{alert_name}
Finds the playbook(s) for a given alert. alert_name can be a short keyword ("DCSync") or a full rule title as it appears in scan_evtx/get_hayabusa_rules output ("Active Directory Replication Rights Abuse (DCSync)"). Matching happens in two passes:
Trigger keyword — case-insensitive substring match (either direction) against each playbook's
triggerslist.Technique overlap (fallback, only tried if step 1 finds nothing) — resolves
alert_nameagainst our curatedrules/by title/filename substring, then matches on shared ATT&CK technique IDs with each playbook'stechniqueslist. This lets an alert title that isn't in anytriggerslist still resolve correctly, as long as it maps to one of our curated rules.
{
"alert_name": "DCSync",
"match_type": "trigger_keyword",
"count": 1,
"playbooks": [ { "id": "credential-theft", "...": "..." } ]
}match_type is "trigger_keyword", "technique_overlap", or null if nothing matched either way (playbooks is then []).
detection://environment/hosts, detection://environment/services, detection://environment/baselines
Expose environment-specific knowledge from ./environment/ — an example inventory shipped with this repo (illustrative hostnames/IPs, not a real network) meant to be replaced with your actual environment. Each resource reads one YAML file and returns its list of entries as-is (no filtering/summarizing, since these are already small curated catalogs):
detection://environment/hosts(environment/hosts.yml) — known hosts and their roles, e.g.{"hostname": "DC01", "role": "domain-controller", "criticality": "critical", "notes": "..."}. A fleet can usehostname_pattern(e.g."WKSTN-*") instead ofhostnameto avoid one line per machine.detection://environment/services(environment/services.yml) — critical services, the hosts they run on, ports, ownership, and criticality, e.g. Active Directory, file shares, mail.detection://environment/baselines(environment/baselines.yml) — normal-vs-anomalous behavior per host role (or a specific hostname), e.g. "interactive logons to DC01/DC02 should only come from JUMP01" — useful for judging whether a detection is consistent with how the environment is expected to behave, or is a genuine outlier.
{
"count": 5,
"baselines": [
{
"scope": "domain-controller",
"description": "Expected baseline behavior for DC01/DC02.",
"business_hours": "Mon-Fri 20:00-23:00 UTC (change window); otherwise no planned interactive activity",
"normal": [ "Interactive/RDP logons only from JUMP01, by Identity/AD Team admins.", "..." ],
"anomalous": [ "Any NTLM logon (EventID 4624 Type 3, AuthenticationPackageName NTLM) - see pass-the-hash playbook.", "..." ]
}
]
}Each resource returns {"error": "..."} if environment/ or the specific .yml file is missing, unreadable, or malformed (not a list under the expected top-level key).
detection://investigations, detection://investigations/{case_id}, detection://investigations/by-technique/{tid}
Expose past investigation case notes from ./investigations/ — an example set of 4 closed cases shipped with this repo (illustrative, not real incidents), one YAML file per case, cross-referenced to the environment/ inventory, rules/, and playbooks/ used in this repo.
detection://investigations— lists every case, summarized (case_id,title,status,disposition,severity,opened,closed,techniques,hosts, first line ofsummary,file).detection://investigations/{case_id}— one case's full notes plus raw YAML, looked up by case ID (e.g.CASE-2026-0031orcase-2026-0031, case-insensitive — matched against the.ymlfilename stem). Full notes includetimeline,findings,root_cause,remediation, andlessons_learned.detection://investigations/by-technique/{tid}— lists cases whosetechniquesinclude a given ATT&CK ID, e.g.T1003.006(case-insensitive, with or without the leadingT— same normalization asdetection://rules/by-technique/{technique_id}).
{
"count": 1,
"investigations": [
{
"case_id": "CASE-2026-0031",
"title": "DCSync detected against DC01 from over-privileged backup service account",
"status": "closed",
"disposition": "true_positive",
"severity": "critical",
"opened": "2026-03-04",
"closed": "2026-03-06",
"techniques": ["T1003.006"],
"hosts": ["DC01"],
"summary": "A directory replication request (EventID 4662, DS-Replication-Get-Changes",
"file": "case-2026-0031.yml"
}
]
}One of the example cases (CASE-2026-0085) is a documented false positive — a real gap found in lsass_access_sysmon.yml's filter (it excludes MsMpEng.exe only by a System32/SysWOW64 path prefix, not Defender's actual ProgramData\Microsoft\Windows Defender\Platform\... install path) — and another (CASE-2026-0072) documents a confirmed detection gap (externally-sourced password spraying against a VPN gateway, which password_spray_4688.yml can't see since it only detects on-host spray tooling). Both illustrate how investigation notes are meant to feed back into rule tuning via suggest_rule/manual edits, not just record what happened.
Returns {"error": "..."} for a missing investigations/ directory, an unknown/invalid case ID, or a malformed case file.
Tool: analyze_coverage
Analyzes our ./rules/ coverage for either a single ATT&CK technique or an entire tactic, using the ATT&CK cache to know which techniques exist. For a technique ID this returns the same shape as detection://attack/techniques/{technique_id} (it's built on the same helper). For a tactic name it walks every technique MITRE assigns to that tactic and classifies each covered/partial/gap, so gaps in the ruleset are visible without checking techniques one at a time.
Parameters:
target(string, required) — either a technique ID (T1003.001,t1558.003,1003.006are equivalent) or a tactic name (credential-access,Lateral Movement,lateral_movementare equivalent — matched case-insensitively, spaces/underscores treated as hyphens)
Returns (technique query):
{
"query_type": "technique",
"technique_id": "T1003.006",
"coverage": "covered",
"rules": [ { "name": "dcsync_4662", "...": "..." } ],
"name": "DCSync",
"description": "...",
"tactics": ["credential-access"],
"url": "https://attack.mitre.org/techniques/T1003/006"
}Returns (tactic query):
{
"query_type": "tactic",
"tactic": "credential-access",
"total_techniques": 67,
"covered_count": 3,
"partial_count": 0,
"gap_count": 64,
"covered": [
{ "technique_id": "T1003.001", "name": "LSASS Memory", "is_subtechnique": true,
"rules": [ { "name": "lsass_access_sysmon", "title": "...", "status": "stable" } ] }
],
"partial": [],
"gaps": [
{ "technique_id": "T1552.004", "name": "Private Keys", "is_subtechnique": true }
]
}Requires the ATT&CK cache from download_attack_data.py — without it, a technique query still returns coverage/rules (with name/description null, same as the resource), but a tactic query returns {"error": "..."} since it has no way to enumerate that tactic's techniques. An unrecognized tactic name returns {"error": "...", "known_tactics": [...]} listing the valid tactic names.
Tool: suggest_rule
Checks a single ATT&CK technique's coverage (same lookup as analyze_coverage/detection://attack/techniques/{technique_id}) and, if it's a genuine gap, suggests where to start looking and can write a starter Sigma template to ./rules/.
Parameters:
technique_id(string, required) — e.g.T1110.003(case-insensitive, with or without the leadingT)create_rule(boolean, optional, defaultfalse) — iftrueand the technique is a gap, writes a starter.ymltemplate to./rules/rule_name(string, optional) — filename stem for the created template. Defaults totemplate_t<id_with_underscores>, e.g.template_t1110_003
Returns (gap, no creation):
{
"technique_id": "T1552.004",
"coverage": "gap",
"existing_rules": [],
"name": "Private Keys",
"tactics": ["credential-access"],
"suggestion": {
"tactics_used": ["credential-access"],
"suggested_logsource": { "product": "windows", "service": "security" },
"suggested_signals": [
"Security EventID 4624/4625 (logon), 4768/4769 (Kerberos TGT/TGS), 4662 (directory service access), 4776 (NTLM validation)",
"Sysmon EventID 10 (ProcessAccess) if the technique targets LSASS or another credential store process"
],
"guidance": "Identify the specific Windows or Sysmon event that captures Private Keys activity, then narrow the selection to field values unique to this technique rather than the tactic in general."
},
"template_created": false,
"template_note": "Pass create_rule=True to write a starter rule template to rules/."
}The suggestion is a coarse, tactic-level starting point (which log source and event types to look at first) drawn from a small built-in table (TACTIC_DETECTION_HINTS in server.py) covering all 14 MITRE Enterprise tactics — it is not technique-specific detection logic, since that requires knowing the technique's actual artifacts (specific command lines, registry keys, API calls, etc.), which isn't something this server can derive automatically.
With create_rule=true, the response additionally includes "template_created": true, "template_path", and the generated YAML as "template_raw". The template has a real id (freshly generated UUID), status: experimental, ATT&CK-derived tags/references, and a suggested logsource, but its detection: block is a placeholder (EventID: 0) marked # TODO — it's meant to be hand-edited, not scanned as-is.
If the technique already has partial or covered coverage, suggestion is null and no template is created (even with create_rule=true) — the response points at the existing_rules to improve instead, so gap-filling doesn't create redundant or conflicting rules for a technique that already has one. Coverage is re-derived live each call, so once a suggested template (or a hand-written rule) exists, a later suggest_rule/analyze_coverage call for the same technique reports partial instead of gap.
Requirements
Python with the
mcpandpyyamllibraries (seerequirements.txt)The Hayabusa CLI, installed via
download_hayabusa.py(Optional) MITRE ATT&CK technique data, installed via
download_attack_data.py, fordetection://attack/techniques/{technique_id}to return technique name/description/tactics
This server cannot be deployed
Maintenance
Related MCP Connectors
A paid remote MCP for developer endpoint scanner MCP, built to return verdicts, receipts, usage logs
VirusTotal MCP — file / URL / domain / IP reputation (BYO key)
A paid remote MCP for ClawManager, built to return verdicts, receipts, usage logs, and audit-ready J
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceAn MCP server that wraps the Hayabusa CLI, enabling analysis of Windows EVTX event log files and browsing of its detection rule set.-
- AlicenseAqualityBmaintenanceEnables MCP clients to run Hayabusa detection scans over Windows event log (.evtx) files for forensic analysis and threat hunting.2MIT
- FlicenseNot gradedqualityCmaintenanceEnables EVTX (Windows Event Log) analysis via Hayabusa, providing tools to scan event logs and retrieve detection rules.-
- FlicenseNot gradedqualityBmaintenanceEnables Windows Event Log (EVTX) analysis using Hayabusa, with options to filter by severity, rule, and output format.-