security-detections-mcp 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,8 +2,106 @@
2
2
 
3
3
  An MCP (Model Context Protocol) server that lets LLMs query a unified database of **Sigma**, **Splunk ESCU**, **Elastic**, and **KQL** security detection rules.
4
4
 
5
+ > **New here? Start with the [Setup Guide](./SETUP.md)** -- covers macOS, Windows (WSL & native), and Linux step by step.
6
+
7
+ ## What's New in 3.0 - Autonomous Detection Platform
8
+
9
+ Version 3.0 transforms this MCP into a **fully autonomous detection engineering platform**. Feed it threat intelligence, and it automatically:
10
+
11
+ 1. **Extracts TTPs** from threat reports, CISA alerts, or manual input
12
+ 2. **Analyzes coverage gaps** against your existing detections
13
+ 3. **Generates detections** in your SIEM's native format (SPL, KQL, EQL, or Sigma)
14
+ 4. **Runs Atomic Red Team tests** against your lab environment
15
+ 5. **Validates detections fire** by querying your SIEM
16
+ 6. **Exports attack data** for reproducibility
17
+ 7. **Stages DRAFT PRs** to your detection repo (never auto-merges)
18
+
19
+ > **Multi-SIEM**: Set `SIEM_PLATFORM` to `splunk`, `sentinel`, `elastic`, or `sigma` in your `.env`. The pipeline was built on Splunk + Attack Range but adapts to any SIEM. See the **[E2E Testing Guide](./docs/E2E-TESTING-GUIDE.md)** for complete setup instructions per platform.
20
+
21
+ ### Architecture: LangGraph + Cursor Subagents
22
+
23
+ The 3.0 architecture uses two complementary systems:
24
+
25
+ | Component | Purpose | Location |
26
+ |-----------|---------|----------|
27
+ | **LangGraph Pipeline** | Core autonomous workflow - portable, testable, CI/CD ready | `agents/` |
28
+ | **Cursor Subagents** | Interactive IDE agents for manual tasks | `.cursor/agents/` |
29
+
30
+ ### Quick Start - Autonomous Mode
31
+
32
+ **Prerequisites**: Node.js 20+, an Anthropic API key. Full details in the [Setup Guide](./SETUP.md).
33
+
34
+ ```bash
35
+ # Install the agents package
36
+ cd agents && npm install --registry https://registry.npmjs.org/
37
+
38
+ # Configure
39
+ cp .env.example .env
40
+ # Edit .env: set SIEM_PLATFORM, ANTHROPIC_API_KEY, SECURITY_CONTENT_PATH
41
+
42
+ # Test with dry run first (uses mock data, no LLM calls)
43
+ DRY_RUN=true npm run orchestrate -- --type technique --input "T1566.004 Spearphishing Voice"
44
+
45
+ # Run with real LLM (creates actual detections)
46
+ npm run orchestrate -- --type technique --input "T1566.004 Spearphishing Voice"
47
+
48
+ # Or analyze a CISA alert
49
+ npm run orchestrate -- --type cisa_alert --url https://www.cisa.gov/news-events/alerts/...
50
+
51
+ # Or feed it a threat report
52
+ npm run orchestrate -- --type threat_report --file ./report.md
53
+
54
+ # Note: Use T1566.004 for testing - it has no existing coverage so will create a detection
55
+ # T1003.001 has 100+ existing detections, so the pipeline will correctly skip it (no gap)
56
+ ```
57
+
58
+ ### Pipeline Stages
59
+
60
+ ```
61
+ ┌─────────────┐ ┌──────────────────┐ ┌────────────────────┐
62
+ │ CTI Analyst │───>│ Coverage Analyzer│───>│ Detection Engineer │
63
+ └─────────────┘ └──────────────────┘ └────────────────────┘
64
+
65
+
66
+ ┌───────────┐ ┌──────────────────┐ ┌──────────────────────┐
67
+ │ PR Stager │<───│ Data Dumper │<───│ Splunk Validator │
68
+ └───────────┘ └──────────────────┘ └──────────────────────┘
69
+
70
+
71
+ ┌──────────────────┐
72
+ │ Atomic Executor │
73
+ └──────────────────┘
74
+ ```
75
+
76
+ ### MCP Integration
77
+
78
+ The autonomous pipeline integrates with existing MCPs:
79
+ - **security-detections** - Coverage analysis and gap identification
80
+ - **splunk-mcp** - Detection validation (`run_detection`, `export_dump`)
81
+ - **mitre-attack** - Technique lookups
82
+
83
+ ### Human-in-the-Loop
84
+
85
+ **CRITICAL**: The system NEVER auto-commits or auto-merges. All PRs are created as **DRAFT** requiring human review:
86
+
87
+ ```
88
+ [PR Stager] ✓ security_content DRAFT PR created: https://github.com/splunk/security_content/pull/123
89
+ [PR Stager] ✓ attack_data DRAFT PR created: https://github.com/splunk/attack_data/pull/456
90
+ ```
91
+
92
+ See the [Autonomous Platform Documentation](./docs/AUTONOMOUS.md) for full details, and the [E2E Testing Guide](./docs/E2E-TESTING-GUIDE.md) for per-SIEM setup (Splunk, Sentinel, Elastic, Sigma).
93
+
5
94
  [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=security-detections&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInNlY3VyaXR5LWRldGVjdGlvbnMtbWNwIl0sImVudiI6eyJTSUdNQV9QQVRIUyI6Ii9wYXRoL3RvL3NpZ21hL3J1bGVzLC9wYXRoL3RvL3NpZ21hL3J1bGVzLXRocmVhdC1odW50aW5nIiwiU1BMVU5LX1BBVEhTIjoiL3BhdGgvdG8vc2VjdXJpdHlfY29udGVudC9kZXRlY3Rpb25zIiwiU1RPUllfUEFUSFMiOiIvcGF0aC90by9zZWN1cml0eV9jb250ZW50L3N0b3JpZXMiLCJFTEFTVElDX1BBVEhTIjoiL3BhdGgvdG8vZGV0ZWN0aW9uLXJ1bGVzL3J1bGVzIiwiS1FMX1BBVEhTIjoiL3BhdGgvdG8va3FsLXJ1bGVzIn19)
6
95
 
96
+ > **Detailed setup**: See the **[Setup Guide](./SETUP.md)** for step-by-step install on macOS, Windows (WSL & native), and Linux with troubleshooting for common issues.
97
+
98
+ ## 🐛 Version 2.1.1 (Bug Fix)
99
+
100
+ - **Fixed Windows EBUSY crash** - SQLite database recreation now handles Windows file locking with retry logic. Previously, Windows users would get `EBUSY: resource busy or locked` on startup.
101
+ - **SQLite journal cleanup** - WAL, SHM, and journal companion files are now cleaned up during database recreation.
102
+ - **Windows CI** - Added Windows to the CI matrix. Build, tests, and full Sigma indexing pipeline now run on both Linux and Windows.
103
+ - **Cross-platform test suite** - New `tests/cross-platform-test.js` validates database lifecycle on all platforms. New `tests/ci-integration-test.js` downloads and indexes 3,200+ Sigma rules to validate the full pipeline.
104
+
7
105
  ## 🚀 Version 2.1 Features
8
106
 
9
107
  **Security Detections MCP v2.1** introduces powerful new capabilities for detection engineering intelligence, analytical memory, autonomous analysis, and advanced MCP protocol features:
@@ -29,6 +29,7 @@ export declare function clearDb(): void;
29
29
  /**
30
30
  * Force recreation of the database.
31
31
  * Useful when schema changes require a fresh start.
32
+ * Handles Windows file locking (EBUSY) with retry logic.
32
33
  */
33
34
  export declare function recreateDb(): void;
34
35
  /**
@@ -4,7 +4,7 @@
4
4
  * Manages SQLite connection singleton, path management, and database lifecycle.
5
5
  */
6
6
  import Database from 'better-sqlite3';
7
- import { homedir } from 'os';
7
+ import { homedir, platform } from 'os';
8
8
  import { join } from 'path';
9
9
  import { mkdirSync, existsSync, unlinkSync } from 'fs';
10
10
  import { createSchema } from './schema.js';
@@ -143,18 +143,51 @@ export function clearDb() {
143
143
  const database = initDb();
144
144
  database.exec('DELETE FROM detections');
145
145
  }
146
+ /**
147
+ * Safely delete a file with retry logic for Windows.
148
+ * Windows can throw EBUSY/EPERM if the file handle isn't fully released yet.
149
+ */
150
+ function safeUnlink(filePath, maxRetries = 5, delayMs = 100) {
151
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
152
+ try {
153
+ if (existsSync(filePath)) {
154
+ unlinkSync(filePath);
155
+ }
156
+ return;
157
+ }
158
+ catch (err) {
159
+ const code = err.code;
160
+ // EBUSY = file is busy, EPERM = operation not permitted, EACCES = access denied
161
+ if ((code === 'EBUSY' || code === 'EPERM' || code === 'EACCES') && attempt < maxRetries - 1) {
162
+ // Spin-wait since we need synchronous behavior
163
+ const end = Date.now() + delayMs * (attempt + 1);
164
+ while (Date.now() < end) { /* wait */ }
165
+ continue;
166
+ }
167
+ throw err;
168
+ }
169
+ }
170
+ }
146
171
  /**
147
172
  * Force recreation of the database.
148
173
  * Useful when schema changes require a fresh start.
174
+ * Handles Windows file locking (EBUSY) with retry logic.
149
175
  */
150
176
  export function recreateDb() {
151
177
  if (db) {
152
178
  db.close();
153
179
  db = null;
154
180
  }
155
- if (existsSync(DB_PATH)) {
156
- unlinkSync(DB_PATH);
181
+ // Small delay on Windows to let file handles fully release
182
+ if (platform() === 'win32') {
183
+ const end = Date.now() + 100;
184
+ while (Date.now() < end) { /* wait */ }
157
185
  }
186
+ // Delete main db and SQLite journal/WAL files
187
+ safeUnlink(DB_PATH);
188
+ safeUnlink(DB_PATH + '-wal');
189
+ safeUnlink(DB_PATH + '-shm');
190
+ safeUnlink(DB_PATH + '-journal');
158
191
  }
159
192
  /**
160
193
  * Check if the database file exists.
package/dist/db.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import Database from 'better-sqlite3';
2
- import { homedir } from 'os';
2
+ import { homedir, platform } from 'os';
3
3
  import { join } from 'path';
4
4
  import { mkdirSync, existsSync, unlinkSync } from 'fs';
5
5
  const CACHE_DIR = join(homedir(), '.cache', 'security-detections-mcp');
@@ -158,15 +158,43 @@ export function clearDb() {
158
158
  const database = initDb();
159
159
  database.exec('DELETE FROM detections');
160
160
  }
161
+ // Safely delete a file with retry logic for Windows (EBUSY/EPERM)
162
+ function safeUnlink(filePath, maxRetries = 5, delayMs = 100) {
163
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
164
+ try {
165
+ if (existsSync(filePath)) {
166
+ unlinkSync(filePath);
167
+ }
168
+ return;
169
+ }
170
+ catch (err) {
171
+ const code = err.code;
172
+ if ((code === 'EBUSY' || code === 'EPERM' || code === 'EACCES') && attempt < maxRetries - 1) {
173
+ const end = Date.now() + delayMs * (attempt + 1);
174
+ while (Date.now() < end) { /* wait */ }
175
+ continue;
176
+ }
177
+ throw err;
178
+ }
179
+ }
180
+ }
161
181
  // Force recreation of the database (needed when schema changes)
182
+ // Handles Windows file locking with retry logic
162
183
  export function recreateDb() {
163
184
  if (db) {
164
185
  db.close();
165
186
  db = null;
166
187
  }
167
- if (existsSync(DB_PATH)) {
168
- unlinkSync(DB_PATH);
188
+ // Small delay on Windows to let file handles fully release
189
+ if (platform() === 'win32') {
190
+ const end = Date.now() + 100;
191
+ while (Date.now() < end) { /* wait */ }
169
192
  }
193
+ // Delete main db and SQLite journal/WAL files
194
+ safeUnlink(DB_PATH);
195
+ safeUnlink(DB_PATH + '-wal');
196
+ safeUnlink(DB_PATH + '-shm');
197
+ safeUnlink(DB_PATH + '-journal');
170
198
  }
171
199
  export function insertDetection(detection) {
172
200
  const database = initDb();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "security-detections-mcp",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "Advanced MCP server for security detections with Detection Engineering Intelligence, Knowledge Graph (Tribal Knowledge), Elicitation, and Resource Subscriptions",
5
5
  "sigmaSpecVersion": "2.0.0",
6
6
  "type": "module",
@@ -20,7 +20,9 @@
20
20
  "build": "tsc",
21
21
  "start": "node dist/index.js",
22
22
  "dev": "tsc --watch",
23
- "test": "npm run build && node tests/integration-test.js && node tests/engineering-tools-test.js",
23
+ "test": "npm run build && node tests/cross-platform-test.js && node tests/integration-test.js && node tests/engineering-tools-test.js",
24
+ "test:platform": "npm run build && node tests/cross-platform-test.js",
25
+ "test:ci": "npm run build && node tests/ci-integration-test.js",
24
26
  "test:integration": "npm run build && node tests/integration-test.js",
25
27
  "test:engineering": "npm run build && node tests/engineering-tools-test.js",
26
28
  "lint": "tsc --noEmit --strict",