security-detections-mcp 3.2.1 → 3.3.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.
@@ -17,6 +17,9 @@ const SPLUNK_PATHS = parsePaths(process.env.SPLUNK_PATHS);
17
17
  const ELASTIC_PATHS = parsePaths(process.env.ELASTIC_PATHS);
18
18
  const STORY_PATHS = parsePaths(process.env.STORY_PATHS);
19
19
  const KQL_PATHS = parsePaths(process.env.KQL_PATHS);
20
+ const SUBLIME_PATHS = parsePaths(process.env.SUBLIME_PATHS);
21
+ const CQL_HUB_PATHS = parsePaths(process.env.CQL_HUB_PATHS);
22
+ const JAMF_PROTECT_PATHS = parsePaths(process.env.JAMF_PROTECT_PATHS);
20
23
  // =============================================================================
21
24
  // Saved Query Tools
22
25
  // =============================================================================
@@ -154,10 +157,10 @@ const rebuildIndexTool = defineTool({
154
157
  handler: async (args) => {
155
158
  const confirmArg = args?.confirm;
156
159
  const skipElicitation = args?.skip_elicitation;
157
- if (SIGMA_PATHS.length === 0 && SPLUNK_PATHS.length === 0 && ELASTIC_PATHS.length === 0 && KQL_PATHS.length === 0) {
160
+ if (SIGMA_PATHS.length === 0 && SPLUNK_PATHS.length === 0 && ELASTIC_PATHS.length === 0 && KQL_PATHS.length === 0 && SUBLIME_PATHS.length === 0 && CQL_HUB_PATHS.length === 0 && JAMF_PROTECT_PATHS.length === 0) {
158
161
  return {
159
162
  error: true,
160
- message: 'No paths configured. Set SIGMA_PATHS, SPLUNK_PATHS, ELASTIC_PATHS, and/or KQL_PATHS environment variables.',
163
+ message: 'No paths configured. Set SIGMA_PATHS, SPLUNK_PATHS, ELASTIC_PATHS, KQL_PATHS, SUBLIME_PATHS, CQL_HUB_PATHS, and/or JAMF_PROTECT_PATHS environment variables.',
161
164
  };
162
165
  }
163
166
  const currentStats = getStats();
@@ -225,7 +228,7 @@ const rebuildIndexTool = defineTool({
225
228
  console.error('[security-detections-mcp] Rebuilding index...');
226
229
  // Recreate DB to apply schema changes
227
230
  recreateDb();
228
- const result = indexDetections(SIGMA_PATHS, SPLUNK_PATHS, STORY_PATHS, ELASTIC_PATHS, KQL_PATHS);
231
+ const result = indexDetections(SIGMA_PATHS, SPLUNK_PATHS, STORY_PATHS, ELASTIC_PATHS, KQL_PATHS, SUBLIME_PATHS, CQL_HUB_PATHS, JAMF_PROTECT_PATHS);
229
232
  // Notify subscribers that resources have changed
230
233
  try {
231
234
  await notifyResourceChange('detection://stats');
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { defineTool } from '../registry.js';
8
8
  import { isStixLoaded, getActorByName, listActors, getActorTechniques, getActorCoverage, getSoftwareForActor, getAttackStats, generateNavigatorLayer, } from '../../db/index.js';
9
- const SOURCE_TYPES = ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'];
9
+ const SOURCE_TYPES = ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'];
10
10
  function stixNotLoadedError() {
11
11
  return {
12
12
  error: true,
@@ -24,7 +24,7 @@ export const analysisTools = [
24
24
  properties: {
25
25
  source_type: {
26
26
  type: 'string',
27
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
27
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
28
28
  description: 'Filter by source type',
29
29
  },
30
30
  tactic: {
@@ -67,7 +67,7 @@ export const analysisTools = [
67
67
  properties: {
68
68
  source_type: {
69
69
  type: 'string',
70
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
70
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
71
71
  description: 'Filter by source type (optional - analyzes all if not specified)',
72
72
  },
73
73
  },
@@ -91,7 +91,7 @@ export const analysisTools = [
91
91
  },
92
92
  source_type: {
93
93
  type: 'string',
94
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
94
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
95
95
  description: 'Filter by source type (optional)',
96
96
  },
97
97
  },
@@ -125,7 +125,7 @@ export const analysisTools = [
125
125
  },
126
126
  source_type: {
127
127
  type: 'string',
128
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
128
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
129
129
  description: 'Filter by source type (optional)',
130
130
  },
131
131
  },
@@ -177,7 +177,7 @@ export const analysisTools = [
177
177
  },
178
178
  source_type: {
179
179
  type: 'string',
180
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
180
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
181
181
  description: 'Filter to specific source type (optional — includes all if omitted)',
182
182
  },
183
183
  tactic: {
@@ -228,7 +228,7 @@ export const analysisTools = [
228
228
  },
229
229
  source_type: {
230
230
  type: 'string',
231
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
231
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
232
232
  description: 'Filter to specific source (optional — analyzes all if omitted)',
233
233
  },
234
234
  include_query_snippets: {
@@ -266,7 +266,7 @@ export const analysisTools = [
266
266
  type: 'array',
267
267
  items: {
268
268
  type: 'string',
269
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
269
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
270
270
  },
271
271
  description: 'Sources to compare (default: all available)',
272
272
  },
@@ -15,7 +15,7 @@ export const comparisonTools = [
15
15
  },
16
16
  source_type: {
17
17
  type: 'string',
18
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
18
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
19
19
  description: 'Optional: filter by source type',
20
20
  },
21
21
  limit: {
@@ -147,7 +147,7 @@ export const comparisonTools = [
147
147
  },
148
148
  source_type: {
149
149
  type: 'string',
150
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
150
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
151
151
  description: 'Optional: filter to specific source',
152
152
  },
153
153
  },
@@ -235,7 +235,7 @@ export const comparisonTools = [
235
235
  properties: {
236
236
  source_type: {
237
237
  type: 'string',
238
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
238
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
239
239
  description: 'Filter by source type (optional)',
240
240
  },
241
241
  },
@@ -10,7 +10,7 @@ export const filterTools = [
10
10
  properties: {
11
11
  source_type: {
12
12
  type: 'string',
13
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
13
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
14
14
  description: 'Source type to filter by',
15
15
  },
16
16
  limit: {
@@ -22,7 +22,7 @@ export const searchTools = [
22
22
  },
23
23
  source_type: {
24
24
  type: 'string',
25
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
25
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
26
26
  description: 'Filter results by detection source type',
27
27
  },
28
28
  },
@@ -27,7 +27,7 @@ const getQueryPatternsTool = defineTool({
27
27
  },
28
28
  source_type: {
29
29
  type: 'string',
30
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
30
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
31
31
  description: 'Filter patterns by source type (optional)',
32
32
  },
33
33
  },
@@ -175,7 +175,7 @@ const findSimilarDetectionsTool = defineTool({
175
175
  },
176
176
  source_type: {
177
177
  type: 'string',
178
- enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql'],
178
+ enum: ['sigma', 'splunk_escu', 'elastic', 'kql', 'sublime', 'crowdstrike_cql', 'jamf_protect'],
179
179
  description: 'Filter by source type (optional)',
180
180
  },
181
181
  limit: {
@@ -10,7 +10,7 @@ export interface Detection {
10
10
  name: string;
11
11
  description: string;
12
12
  query: string;
13
- source_type: 'sigma' | 'splunk_escu' | 'elastic' | 'kql' | 'sublime' | 'crowdstrike_cql';
13
+ source_type: 'sigma' | 'splunk_escu' | 'elastic' | 'kql' | 'sublime' | 'crowdstrike_cql' | 'jamf_protect';
14
14
  mitre_ids: string[];
15
15
  logsource_category: string | null;
16
16
  logsource_product: string | null;
@@ -49,7 +49,7 @@ export interface Detection {
49
49
  export interface DetectionSummary {
50
50
  id: string;
51
51
  name: string;
52
- source_type: 'sigma' | 'splunk_escu' | 'elastic' | 'kql' | 'sublime' | 'crowdstrike_cql';
52
+ source_type: 'sigma' | 'splunk_escu' | 'elastic' | 'kql' | 'sublime' | 'crowdstrike_cql' | 'jamf_protect';
53
53
  mitre_ids: string[];
54
54
  severity: string | null;
55
55
  mitre_tactics: string[];
@@ -190,6 +190,31 @@ export interface ElasticTechnique {
190
190
  reference?: string;
191
191
  subtechnique?: ElasticTechnique[];
192
192
  }
193
+ /**
194
+ * Jamf Protect custom analytic detection structure (YAML with NSPredicate filter).
195
+ * @see https://github.com/jamf/jamfprotect/tree/main/custom_analytic_detections
196
+ */
197
+ export interface JamfProtectRule {
198
+ name: string;
199
+ uuid?: string;
200
+ label?: string;
201
+ shortDescription?: string;
202
+ longDescription?: string;
203
+ level?: number;
204
+ inputType?: 'GPProcessEvent' | 'GPFSEvent' | 'GPKeylogRegisterEvent' | 'GPUSBEvent' | string;
205
+ filter: string;
206
+ severity?: 'Informational' | 'Low' | 'Medium' | 'High' | 'Critical' | string;
207
+ categories?: string[];
208
+ MitreCategories?: string[] | null;
209
+ tags?: string[] | null;
210
+ snapshotFiles?: string[] | null;
211
+ actions?: Array<{
212
+ name?: string;
213
+ } | string>;
214
+ context?: string[] | null;
215
+ version?: number;
216
+ remediation?: string | null;
217
+ }
193
218
  /**
194
219
  * CQL Hub rule structure (CrowdStrike Query Language)
195
220
  * @see https://github.com/ByteRay-Labs/Query-Hub
@@ -11,7 +11,7 @@
11
11
  * - dynamic: Dynamic table types for runtime schema extension
12
12
  * - meta: Meta-tool types for custom tools and workflows
13
13
  */
14
- export type { Detection, DetectionSummary, SigmaRule, SplunkDetection, ElasticRule, ElasticThreat, ElasticTechnique, SublimeRule, CqlHubRule, } from './detection.js';
14
+ export type { Detection, DetectionSummary, SigmaRule, SplunkDetection, ElasticRule, ElasticThreat, ElasticTechnique, SublimeRule, CqlHubRule, JamfProtectRule, } from './detection.js';
15
15
  export type { AnalyticStory, SplunkStoryYaml, } from './story.js';
16
16
  export type { IndexStats, SourceComparison, SavedQuery, } from './stats.js';
17
17
  export type { KnowledgeEntity, KnowledgeRelation, KnowledgeObservation, KnowledgeDecision, KnowledgeLearning, KnowledgeQueryOptions, } from './knowledge.js';
@@ -12,6 +12,8 @@ export interface IndexStats {
12
12
  elastic: number;
13
13
  kql: number;
14
14
  sublime: number;
15
+ crowdstrike_cql: number;
16
+ jamf_protect: number;
15
17
  by_severity: Record<string, number>;
16
18
  by_logsource_product: Record<string, number>;
17
19
  mitre_coverage: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "security-detections-mcp",
3
- "version": "3.2.1",
3
+ "version": "3.3.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,11 +20,12 @@
20
20
  "build": "tsc",
21
21
  "start": "node dist/index.js",
22
22
  "dev": "tsc --watch",
23
- "test": "npm run build && node tests/cross-platform-test.js && node tests/integration-test.js && node tests/engineering-tools-test.js",
23
+ "test": "npm run build && node tests/cross-platform-test.js && node tests/jamf-parser-test.js && node tests/integration-test.js && node tests/engineering-tools-test.js",
24
24
  "test:platform": "npm run build && node tests/cross-platform-test.js",
25
25
  "test:ci": "npm run build && node tests/ci-integration-test.js",
26
26
  "test:integration": "npm run build && node tests/integration-test.js",
27
27
  "test:engineering": "npm run build && node tests/engineering-tools-test.js",
28
+ "test:jamf": "npm run build && node tests/jamf-parser-test.js",
28
29
  "lint": "tsc --noEmit --strict",
29
30
  "prepublishOnly": "npm run build && npm run lint"
30
31
  },
@@ -43,6 +44,8 @@
43
44
  "sublime",
44
45
  "crowdstrike",
45
46
  "cql",
47
+ "jamf",
48
+ "macos",
46
49
  "siem",
47
50
  "mitre",
48
51
  "attack"