Triage & cases
Start a shift, read the alert queue, and turn alerts into cases with the nano-investigator MCP server
Triage & cases
nano-investigator is an MCP server that exposes the SIEM's alerts, cases, notebooks, search, risk, and enrichment surfaces as agent-callable tools. It runs alongside nanodac and shares the same three environment variables. Where nanodac authors detections and writes rules to the SIEM, nano-investigator runs SOC operations and is mostly read-only.
This page covers the start of a shift: getting a briefing, reading the alert queue, and the one model you have to internalize before you do anything else.
Alerts cannot be mutated. There is no acknowledge, close, or assign tool for an alert. Triage happens by turning an alert into a case: you create or pick a case, attach the alert with add_alert_to_case, and record your reasoning on the case wall with add_case_wall_entry. The alert stays as a read-only signal.
Start of shift: the morning briefing
The fastest way to start is the morning_briefing prompt. It takes one optional argument, hours (default 12), and chains a fixed set of read-only tools into a shift-handoff summary:
get_alert_countspluslist_alertsfiltered to critical and high severityget_case_statsfor open/in-progress case load and average resolution timeget_risky_entitiesfor the top 10 entities by risklist_detectionsto flag rules that are noisy or have gone silenthealth_checkto confirm ClickHouse and PostgreSQL are reachable
It returns a prioritized list of what needs attention, not just raw counts.
> morning briefing for the last 8 hours
Running morning_briefing (hours=8)...
Alerts (last 8h): 4 critical, 11 high, 38 medium (get_alert_counts)
CRIT #1182 Impossible travel — user jdoe (new)
CRIT #1180 Credential dumping — host WIN-FS01 (new)
HIGH #1175 DNS tunneling — 10.5.2.40 (new)
...
Cases: 6 open, 2 in progress, avg resolution 5.2h (get_case_stats)
Top risk: WIN-FS01 (88), jdoe (81), 10.5.2.40 (74) (get_risky_entities)
Detections: rule "Okta MFA fatigue" silent 36h; rule
"Sysmon proc anomaly" fired 1.4k times (likely noisy)
Health: ClickHouse OK, PostgreSQL OK
Suggested order of work:
1. Triage CRIT #1180 (credential dumping) — touches top-risk host
2. Triage CRIT #1182 (impossible travel) — same user as 3 medium alerts
3. Look at "Sysmon proc anomaly" noise before it buries the queueReading the alert queue
Once you know where to look, the three alert tools are all read-only:
list_alertslists with filters. All params are optional:status(new/acknowledged/closed),severity,rule_id,assigned_to,limit(default 50),offset.get_alertreturns the full detail for one alert byid, including the matched events andai_triage_hintscarried over from the detection that fired it.get_alert_countsreturns counts grouped by severity and status.
> show me the new critical alerts
Calling list_alerts (status=new, severity=critical)...
#1182 Impossible travel — user jdoe 2026-05-31 06:12
#1180 Credential dumping — host WIN-FS01 2026-05-31 05:48
> open 1180
Calling get_alert (id=1180)...
Rule: Credential dumping via LSASS access
Severity: critical
Entities: host WIN-FS01, process rundll32.exe, user SYSTEM
Matched: 3 events (Sysmon EventID 10, target lsass.exe)
ai_triage_hints:
ignore_when: ["access from known EDR agent process"]
suspicious_when: ["source process is rundll32 or regsvr32",
"outside maintenance window"]The ai_triage_hints block is the detection author's guidance: read the ignore_when and suspicious_when lists before you decide whether the alert is worth a case.
Checking the risk picture
Two tools give you the org-wide risk view so you can prioritize across the queue rather than top-down:
get_risky_entitiesreturns the top entities by risk score. Optional params:window(24h/7d/all),entity_type,min_score,limit(default 20).get_risk_overviewreturns entity counts by risk level for both the 24h and 7d windows.
An alert against a host that is already the top-risk entity for the week is a different priority than the same alert against a quiet host.
> who are the riskiest entities right now?
Calling get_risky_entities (window=24h, limit=20)...
host WIN-FS01 88 (3 alerts, lateral-movement signals)
user jdoe 81 (impossible travel + failed MFA)
ip 10.5.2.40 74 (DNS tunneling)Turning an alert into a case
This is the actual act of triage. There is no alert state to change, so you move the signal into a case and record what you decided.
Create or pick a case. Use create_case (params: title, severity required; optional description, priority, assigned_to, tags) for a new investigation, or list_cases / get_case to find an existing one to attach to.
Attach the alert. Call add_alert_to_case with case_id and alert_id. Set is_primary when the alert is the case's root signal. You can attach more than one alert to the same case.
Record your reasoning on the wall. Call add_case_wall_entry with case_id, entry_type (comment, ai_analysis, or action_taken), and content. This is the short, human-readable status. Detailed analysis belongs in a notebook (see Investigate alerts).
> alert 1180 looks real. open a case for it and assign to me.
Calling create_case (title="Credential dumping on WIN-FS01",
severity="critical", assigned_to="me")...
→ case #C-204 created
Calling add_alert_to_case (case_id=C-204, alert_id=1180,
is_primary=true)...
→ alert linked
Calling add_case_wall_entry (case_id=C-204, entry_type="comment",
content="LSASS access from rundll32 on WIN-FS01, outside
maintenance window. Matches suspicious_when. Investigating
parent process and lateral movement.")...
→ wall updated
Case C-204 is open and assigned to you. Want me to start the
investigation? (investigate_alert on 1180)Working an existing case
When you pick up a case that already has history, do not page through it piece by piece. Call review_case with the case id or case number. It is a composite read that pulls the case, its wall, and all linked notebooks (entries and references, fetched in batches) in one shot. Use it as the first call whenever you resume a case.
get_related_cases (param: id) surfaces historically similar cases by shared entities, rules, or MITRE techniques, which is how you find out the same host has been investigated before.
Other case tools
The remaining case tools cover status and ownership changes:
update_caseeditstitle,description,severity, ortags.change_case_statussetsstatus(open/in_progress/pending/resolved/closed) and an optionaldisposition(true_positive/false_positive/benign/inconclusive).assign_casereassigns to auser_id.get_case_statsreturns counts by status and severity plus average resolution time.
merge_cases is the one destructive operation. It merges source_case_ids into a target_case_id and closes the source cases as merged. The agent should confirm with you before running it.
What's next
- Investigate alerts: the
investigate_alertprompt, entity pivots, and recording findings in notebooks - Hunt: proactive hunting with
search_sql, prevalence, and MITRE coverage - Detection-as-Code: author and ship the detections that produce these alerts