Detection Workbench
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| DW_CONFIG | No | Override the path to the configuration file. Defaults to ~/.detection-workbench/config.toml. Everything in the configuration is optional. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| create_caseB | Create a case and make it active. Every run, finding and decision is recorded in it. Example: create_case(title="Noisy SID 1000042 on the proxy capture") |
| open_caseC | Make an existing case active. Example: open_case(case_id="20261022-noisy-sid-1000042") |
| list_casesB | List cases in the case directory with ids, titles and status. |
| register_evidenceA | Register a pcap/pcapng or rules file in the active case (hashed, type-detected, never copied or modified). The path must be under allowed_roots. Returns the evidence id (e-0001 ...) used by other tools. Example: register_evidence(path="~/captures/proxy.pcap") |
| add_findingB | Record a short statement supported by specific runs, e.g. 'SID 1000042 fires 300 times, 95% from 10.0.4.20'. Run and evidence ids must exist. Starts as status 'open'. Example: add_finding(statement="SID 1000042 is dominated by one scanner", run_ids=["r-0002"]) |
| update_findingB | Change a finding's status (open, confirmed, dismissed) or wording; history is kept. Example: update_finding(finding_id="f-0001", status="confirmed") |
| add_noteC | Add free-text context to the case. Example: add_note(text="Capture taken during the 14:00 scan window") |
| update_caseA | Write the case summary (your analysis and conclusions, Markdown allowed) and/or set the status to 'open' or 'closed'. The summary appears at the top of the exported report, so cite run and finding ids in it. Call it again to revise; each change is logged. Example: update_case(summary="SID 1000042 is too broad (f-0001, r-0003); the rewrite in r-0005 fixes it.", status="closed") |
| get_caseB | Summary of the active case: evidence, findings, decisions, notes and recent runs. |
| export_caseA | Export the case as a Markdown report ('markdown') or a Timesketch-importable CSV ('timesketch_csv'). Without a path the file goes in the case's exports/ folder. A path must end in .md or .csv and an existing file is only replaced with overwrite=true. Example: export_case(format="markdown") |
| get_statusA | Engine versions and backend (native or Docker), config location, allowed_roots, limits and the active case. Call this first if something is unavailable. |
| pcap_summaryB | Packet count, time range, protocols, top talkers and services for a registered pcap. Example: pcap_summary(evidence_id="e-0001") |
| validate_rulesA | Check rules with Snort itself. Give a registered rules file (rules_id) or inline rules_text. Returns errors as {line, sid, error, plain}, warnings, and workbench_lint hygiene items (e.g. a missing sid, which Snort does not report). Fast enough for a write-test-fix loop. Example: validate_rules(rules_text='alert http any any -> any any ( msg:"x"; http_uri; content:"abc"; sid:1000001; rev:1; )') |
| run_pcapB | Run rules against a registered pcap. Returns the run id, total alerts, counts by SID with msg, the first alerts, and stream_caveats (flows where Snort cannot inspect un-ACKed data). home_net is an IP/CIDR or list like '[10.0.0.0/8,192.168.0.0/16]'; no raw Lua is accepted. Example: run_pcap(pcap_id="e-0001", rules_id="e-0002", home_net="10.0.0.0/8") |
| get_alertsB | Page or filter a run's alerts by SID, source/destination address or packet range. Example: get_alerts(run_id="r-0002", sid=1000042, src="10.0.4.20", limit=20) |
| explain_alertA | Facts about one alert: the rule text and parsed options, the 5-tuple/direction/service, a bounded hex+ASCII dump, and which content/pcre options appear in the payload and at what offsets (wire bytes reassembled from the pcap, plus Snort's own inspected buffer). Report facts; you do the explaining. Example: explain_alert(run_id="r-0002", alert_idx=0) |
| profile_rulesB | Run the rules with Snort's rule profiler and return the slowest rules with checks, matches and time. Example: profile_rules(pcap_id="e-0001", rules_id="e-0002", top=10) |
| suggest_tuning_targetsB | Rank the noisiest SIDs in a run by count, with distinct sources/destinations and how concentrated the hits are in one source. Example: suggest_tuning_targets(run_id="r-0002") |
| test_tuningA | Apply one structured change to a copy, re-run the same pcap, and return before/after counts per SID. Records a decision. change.kind is one of: suppress: {kind, sid, track:'by_src'|'by_dst', ip} event_filter: {kind, sid, type:'limit'|'threshold'|'both', track, count, seconds} rate_filter: {kind, sid, track, count, seconds, new_action, timeout} rule_edit: {kind, sid, rule:''} Example: test_tuning(before_run_id="r-0002", change={"kind":"suppress","sid":1000042,"track":"by_src","ip":"10.0.4.20"}, reason="known scanner") |
| diff_runsC | Alerts added, removed and changed between two runs, grouped by SID. Example: diff_runs(run_a="r-0002", run_b="r-0003") |
| write_rules_fileA | Save rules to a path you name. Existing files are never overwritten unless overwrite=true; instead a diff is returned. Registered evidence is never overwritten. Example: write_rules_file(path="~/rules/local-new.rules", rules_text="alert ...") |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| detection_engineering | How to write, test, explain and tune detections with this workbench. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 21 tools
Each tool targets a distinct resource+action (case CRUD, evidence registration, findings/notes, pcap analysis, tuning tests). A few tools operate on the same run object (get_alerts, explain_alert, suggest_tuning_targets, diff_runs) but their descriptions clearly separate enumeration, single-alert forensics, ranking, and comparison. Case tools like get_case/open_case/update_case are close but distinguishable by their descriptions.
Names use snake_case throughout and are mostly verb_noun (create_case, add_finding, run_pcap, test_tuning). Minor deviations exist, notably the noun-first 'pcap_summary' and the verb-less 'diff_runs', but these remain readable and predictable.
21 tools across case management, evidence, rule validation/execution, alert analysis, and tuning is on the heavier side but each earns a distinct role. The surface feels comprehensive rather than padded for a detection-engineering workflow.
Covers the full case lifecycle (create/open/list/get/update/export), evidence registration, findings, notes, pcap analysis, rule validation, running, alert inspection, profiling, tuning tests, run diffing, and rule writing. Minor gaps: no standalone run listing/summary or evidence listing/removal, so discoverability of past runs relies on get_case.