@jupiterone/jupiterone-mcp 0.0.4 → 0.0.7

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.
Files changed (63) hide show
  1. package/README.md +2 -2
  2. package/dist/client/graphql/mutations.js +13 -10
  3. package/dist/client/graphql/mutations.js.map +1 -1
  4. package/dist/client/graphql/queries.js +17 -14
  5. package/dist/client/graphql/queries.js.map +1 -1
  6. package/dist/client/jupiterone-client.d.ts +6 -3
  7. package/dist/client/jupiterone-client.d.ts.map +1 -1
  8. package/dist/client/jupiterone-client.js +35 -20
  9. package/dist/client/jupiterone-client.js.map +1 -1
  10. package/dist/client/services/account-service.d.ts +1 -0
  11. package/dist/client/services/account-service.d.ts.map +1 -1
  12. package/dist/client/services/account-service.js +9 -4
  13. package/dist/client/services/account-service.js.map +1 -1
  14. package/dist/client/services/alert-service.js +7 -3
  15. package/dist/client/services/alert-service.js.map +1 -1
  16. package/dist/client/services/dashboard-service.d.ts +4 -0
  17. package/dist/client/services/dashboard-service.d.ts.map +1 -1
  18. package/dist/client/services/dashboard-service.js +21 -8
  19. package/dist/client/services/dashboard-service.js.map +1 -1
  20. package/dist/client/services/integration-service.js +11 -7
  21. package/dist/client/services/integration-service.js.map +1 -1
  22. package/dist/client/services/j1ql-service.js +9 -5
  23. package/dist/client/services/j1ql-service.js.map +1 -1
  24. package/dist/client/services/rule-service.d.ts +4 -0
  25. package/dist/client/services/rule-service.d.ts.map +1 -1
  26. package/dist/client/services/rule-service.js +26 -13
  27. package/dist/client/services/rule-service.js.map +1 -1
  28. package/dist/generated/description-map.d.ts +2 -0
  29. package/dist/generated/description-map.d.ts.map +1 -0
  30. package/dist/generated/description-map.js +2300 -0
  31. package/dist/generated/description-map.js.map +1 -0
  32. package/dist/index.js +11 -12
  33. package/dist/index.js.map +1 -1
  34. package/dist/server/mcp-server.d.ts +4 -1
  35. package/dist/server/mcp-server.d.ts.map +1 -1
  36. package/dist/server/mcp-server.js +1535 -1366
  37. package/dist/server/mcp-server.js.map +1 -1
  38. package/dist/types/jupiterone.d.ts +3 -2
  39. package/dist/types/jupiterone.d.ts.map +1 -1
  40. package/dist/types/jupiterone.js +2 -1
  41. package/dist/utils/description-loader.js +8 -5
  42. package/dist/utils/description-loader.js.map +1 -1
  43. package/dist/utils/getEnv.d.ts +2 -0
  44. package/dist/utils/getEnv.d.ts.map +1 -0
  45. package/dist/utils/getEnv.js +16 -0
  46. package/dist/utils/getEnv.js.map +1 -0
  47. package/dist/utils/j1ql-validator.js +5 -1
  48. package/dist/utils/j1ql-validator.js.map +1 -1
  49. package/dist/utils/load-description.d.ts.map +1 -1
  50. package/dist/utils/load-description.js +7 -7
  51. package/dist/utils/load-description.js.map +1 -1
  52. package/package.json +5 -5
  53. package/dist/descriptions/create-dashboard-widget.md +0 -325
  54. package/dist/descriptions/create-dashboard.md +0 -12
  55. package/dist/descriptions/create-inline-question-rule.md +0 -374
  56. package/dist/descriptions/create-j1ql-from-natural-language.md +0 -7
  57. package/dist/descriptions/execute-j1ql-query.md +0 -379
  58. package/dist/descriptions/get-integration-definitions.md +0 -27
  59. package/dist/descriptions/get-integration-instances.md +0 -35
  60. package/dist/descriptions/list-alerts.md +0 -14
  61. package/dist/descriptions/list-rules.md +0 -53
  62. package/dist/descriptions/update-dashboard.md +0 -467
  63. package/dist/descriptions/update-inline-question-rule.md +0 -363
@@ -0,0 +1,2300 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.descriptionMap = void 0;
4
+ /* AUTO-GENERATED — DO NOT EDIT MANUALLY */
5
+ exports.descriptionMap = {
6
+ "create-dashboard-widget.md": `# JupiterOne Create Dashboard Widget Tool
7
+
8
+ **Purpose**: Adds a new widget to a specified JupiterOne dashboard. This tool allows you to programmatically create visual widgets (such as pie charts, bar charts, tables, etc.) on any dashboard, using custom queries and configuration.
9
+
10
+ This tool should be used when:
11
+ - You want to add a new visualization to an existing dashboard
12
+ - You need to automate dashboard widget creation for reporting or monitoring
13
+ - You want to programmatically manage dashboard content
14
+
15
+ ## Required Parameters
16
+ - \`dashboardId\`: The ID of the dashboard to add the widget to
17
+ - \`input\`: The widget configuration object (CreateInsightsWidgetInput), including:
18
+ - \`title\`: Widget title
19
+ - \`description\`: Widget description (optional)
20
+ - \`type\`: Widget type (e.g., 'pie', 'bar', 'table', etc.)
21
+ - \`noResultMessage\`: Message to display when there are no results
22
+ - \`config\`: Widget configuration, including queries and settings
23
+
24
+ ## Supported Chart Types
25
+
26
+ The following values are supported for the \`type\` property when creating a widget:
27
+
28
+ \`\`\`typescript
29
+ export enum ChartType {
30
+ Area = 'area',
31
+ Bar = 'bar',
32
+ Graph = 'graph',
33
+ Line = 'line',
34
+ Matrix = 'matrix',
35
+ Number = 'number',
36
+ Pie = 'pie',
37
+ Table = 'table',
38
+ Status = 'status',
39
+ Markdown = 'markdown',
40
+ }
41
+ \`\`\`
42
+
43
+ ## Example Usage
44
+ \`\`\`json
45
+ {
46
+ "dashboardId": "95936c1a-468a-494f-b11d-b134ac9b9577",
47
+ "input": {
48
+ "title": "Example title",
49
+ "type": "pie",
50
+ "noResultMessage": "Message that shows when no results",
51
+ "config": {
52
+ "queries": [
53
+ {
54
+ "query": "FIND (aws_db_cluster_snapshot|aws_db_snapshot) as snapshot\n RETURN\n snapshot.tag.AccountName as name,\n sum(snapshot.allocatedStorage) * 0.02 as value",
55
+ "name": "Query 1"
56
+ }
57
+ ],
58
+ "settings": {
59
+ "pie": {
60
+ "customColors": {
61
+ "0": "#26A69A",
62
+ "1": "#3F51B5",
63
+ "2": "#D81B60",
64
+ "3": "#FF8F00",
65
+ "4": "#9575CD",
66
+ "5": "#8BC34A",
67
+ "6": "#039BE5"
68
+ },
69
+ "upwardTrendIsGood": true
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ \`\`\`
76
+
77
+ # Widget Options
78
+
79
+ When creating a dashboard, there are several options for widgets to choose from. This allows you to utilize the most impactful visual representation for your data. Below are the supported dashboard widgets, each with their own requirements and examples.
80
+
81
+ ---
82
+
83
+ # Chart Types and Example Queries
84
+
85
+ > **Note:**
86
+ > To enable trend functionality for a chart, set \`trendDataIsEnabled: true\` in the relevant chart type's settings (e.g., \`settings.pie.trendDataIsEnabled\`). You can also use keys like \`trendQueryResultsCount\` to control the number of trend data points, and \`upwardTrendIsGood\` to indicate if an upward trend is positive.
87
+
88
+ ## Number
89
+ The number chart visualization shows one large stat value. In the trend version of this chart you are able to track the value through a spark line to see if the result is getting larger or smaller over time.
90
+
91
+ ### Query Requirements
92
+ Expects only a single \`value\` in the returned query response.
93
+
94
+ ### Example Queries
95
+ **Trend:**
96
+ \`\`\`j1ql
97
+ FIND User AS u
98
+ RETURN count(u) AS value
99
+ \`\`\`
100
+ **Non-Trend:**
101
+ \`\`\`j1ql
102
+ FIND User AS u
103
+ RETURN count(u) AS value
104
+ \`\`\`
105
+
106
+ ---
107
+
108
+ ## Pie Chart
109
+ The pie chart displays values from one or more queries, as they relate to each other, in the form of slices of a pie. The arc length, area and central angle of a slice are all proportional to the slice's value, as it relates to the sum of all values. This type of chart is best used when you want a quick comparison of a small set of values in an aesthetically pleasing form. In the trend version of this chart you are able to track the value change of each slice value as well as the total value through a spark line to see if the data set is getting larger or smaller over time.
110
+
111
+ ### Query Requirements
112
+ Expects 2 or more pairs of \`name\` and numeric \`value\` properties.
113
+
114
+ ### Example Queries
115
+ **Trend:**
116
+ \`\`\`j1ql
117
+ FIND DataStore AS ds
118
+ THAT RELATES TO (Account|Service) AS a
119
+ RETURN
120
+ a.tag.AccountName AS name,
121
+ count(ds) AS value
122
+ \`\`\`
123
+ **Non-Trend 1:**
124
+ \`\`\`j1ql
125
+ FIND DataStore AS ds
126
+ THAT RELATES TO (Account|Service) AS a
127
+ RETURN
128
+ a.tag.AccountName AS name,
129
+ count(ds) AS value
130
+ \`\`\`
131
+ **Non-Trend 2:**
132
+ \`\`\`j1ql
133
+ FIND DataStore AS ds
134
+ THAT RELATES TO (Account|Service) AS a
135
+ RETURN
136
+ count(ds) AS value
137
+ \`\`\`
138
+
139
+ ---
140
+
141
+ ## Bar Chart
142
+ The bar chart visualization allows you to view categorical data to analyze your queries with a specified x and y axis. You are able to run multiple queries and visualize the bar chart in stacked format. This chart is best suited for categorizing your results. In the trend version of the chart you are able to visualize the value change of each categorical result through a %Change indicator and a reference category bar of the result value from the previous time period selected.
143
+
144
+ ### Query Requirements
145
+ Expects one or more \`x\` and \`y\` values.
146
+
147
+ ### Example Queries
148
+ **Trend:**
149
+ \`\`\`j1ql
150
+ FIND Person AS p
151
+ THAT IS User AS u
152
+ THAT opened PR
153
+ WITH state='OPEN' AS pr
154
+ RETURN
155
+ p.displayName AS x,
156
+ count(pr) AS y
157
+ ORDER BY y DESC
158
+ \`\`\`
159
+ **Non-Trend:**
160
+ \`\`\`j1ql
161
+ FIND Person AS p
162
+ THAT IS User AS u
163
+ THAT opened PR
164
+ WITH state='OPEN' AS pr
165
+ RETURN
166
+ p.displayName AS x,
167
+ count(pr) AS y
168
+ ORDER BY y DESC
169
+ LIMIT 5
170
+ \`\`\`
171
+
172
+ ---
173
+
174
+ ## Line Chart
175
+ The line chart is created by plotting a series of several points and connecting them with a straight line. This is best suited for data that has historical trend data enabled.
176
+
177
+ ### Query Requirements
178
+ Expects \`line\` and \`y\` values.
179
+
180
+ ### Example Queries
181
+ **Trend:**
182
+ \`\`\`j1ql
183
+ FIND Finding
184
+ WITH createdOn > date.now-7day AS f
185
+ RETURN
186
+ count(f) AS y,
187
+ f.numericSeverity AS line
188
+ \`\`\`
189
+ **Non-Trend:**
190
+ \`\`\`j1ql
191
+ FIND Finding
192
+ WITH createdOn > date.now-7day AS f
193
+ RETURN
194
+ f.createdOn AS x,
195
+ count(f) AS y,
196
+ f.numericSeverity AS line
197
+ \`\`\`
198
+
199
+ ---
200
+
201
+ ## Matrix Chart
202
+ The matrix chart is used for analyzing and displaying the relationship between data sets. The matrix diagram shows the relationship between two, three, or four groups of information.
203
+
204
+ ### Query Requirements
205
+ Expects \`x\` and \`y\` row and column names. Optional \`label\` to be shown in each cell. Any additional properties returned will be shown as key: value.
206
+
207
+ ### Example Queries
208
+ **Firewall matrix:**
209
+ \`\`\`j1ql
210
+ FIND Firewall AS row
211
+ THAT allows AS rel
212
+ Network AS col
213
+ RETURN
214
+ row.displayName AS x,
215
+ col.displayName AS y,
216
+ rel.egress AS egress,
217
+ rel.ingress AS ingress,
218
+ rel.fromPort as fromPort,
219
+ rel.toPort as toPort,
220
+ rel.ipProtocol AS label
221
+ \`\`\`
222
+
223
+ ---
224
+
225
+ ## Table
226
+ The tables chart present data in as close to raw form as possible. Tables are meant to be read, so they are ideal when you have data that cannot easily be presented visually, or when the data requires more specific attention.
227
+
228
+ ### Query Requirements
229
+ Note: This chart is currently limited to displaying 250 rows, and it does not handle pagination. It is recommended to use LIMIT and ORDER BY to sort and limit the results.
230
+
231
+ ### Example Queries
232
+ **Most recent people:**
233
+ \`\`\`j1ql
234
+ FIND Person AS p
235
+ RETURN
236
+ p.name AS Name,
237
+ p.email AS Email,
238
+ p.manager AS Manager
239
+ ORDER BY p._createdOn DESC
240
+ LIMIT 5
241
+ \`\`\`
242
+
243
+ ---
244
+
245
+ ## Graph Chart
246
+ The graph chart displays a tree graph of query results. This chart is best used to visualize specific relationships between entities.
247
+
248
+ ### Example Queries
249
+ **Most recent people:**
250
+ \`\`\`j1ql
251
+ FIND Person RETURN TREE
252
+ \`\`\`
253
+
254
+ ---
255
+
256
+ ## Status
257
+ The status chart displays a visual summary of correlating queries. This chart is best used to show positive or negative results based on if relationships are present in query results. This chart is best suited by multiple queries.
258
+
259
+ ### Example Queries
260
+ **Users passing security check:**
261
+ \`\`\`j1ql
262
+ Find Person as p
263
+ Return
264
+ p.email as id,
265
+ p.name as displayName,
266
+ p.acceptedSecurityPolicyOn,
267
+ p.backgroundCheck,
268
+ p.iconWebLink as iconWebLink
269
+ \`\`\`
270
+ \`\`\`j1ql
271
+ Find Person as p that owns Device as d
272
+ Return
273
+ p.email as id,
274
+ d.encrypted
275
+ \`\`\`
276
+ \`\`\`j1ql
277
+ Find Person as p that is User as u
278
+ Return
279
+ p.email as id,
280
+ count(u)
281
+ \`\`\`
282
+
283
+ ---
284
+
285
+ ## Area Chart
286
+ The area chart is a graph that combines a line chart and a bar chart to show changes in quantities over time. This chart requires the assets in the query to have relevant dates in their properties. For the best results, these charts can be generated by J1 Questions that have trend collection enabled. (This will soon be available straight from Insights.)
287
+
288
+ ### Query Requirements
289
+ Expects two or more \`x\` and \`y\` values.
290
+
291
+ ### Example Queries
292
+ **Top 5 most open PRs by Person:**
293
+ \`\`\`j1ql
294
+ FIND Person AS p
295
+ THAT IS User AS u
296
+ THAT opened PR
297
+ WITH state='OPEN' AS pr
298
+ RETURN
299
+ p.displayName AS x,
300
+ count(pr) AS y
301
+ ORDER BY y DESC
302
+ LIMIT 5
303
+ \`\`\`
304
+
305
+ ---
306
+
307
+ ## Markdown Chart
308
+ The markdown chart/widget allows you to display custom Markdown content directly on your dashboard. This is useful for adding documentation, instructions, or contextual information alongside your visualizations.
309
+
310
+ ### Query Requirements
311
+ - No queries are required for this widget type.
312
+ - The widget's settings must include a \`markdown.text\` property containing the Markdown content to display.
313
+
314
+ ### Example Configuration
315
+ **Simple Markdown widget:**
316
+ \`\`\`json
317
+ {
318
+ "type": "markdown",
319
+ "config": {
320
+ "queries": [],
321
+ "settings": {
322
+ "markdown": {
323
+ "text": "# test markdown here\nsome more content"
324
+ }
325
+ }
326
+ }
327
+ }
328
+ \`\`\`
329
+
330
+ ---
331
+
332
+ After creating a widget you should include the dashboard url in your response to the user.`,
333
+ "create-dashboard.md": `# Create Dashboard Tool
334
+
335
+ Creates a new dashboard in JupiterOne. This tool is simple and self-descriptive: provide a name and a type to create a dashboard. Unless specified otherwise, default to creating personal dashboards.
336
+ After creating a dashboard and all its widgets, you will typically want to call \`update-dashboard\` tool to set a layout favorable for the user, widgets should never be left at their default size.
337
+
338
+ ## Valid Dashboard Types
339
+ \`\`\`typescript
340
+ export enum DashboardType {
341
+ USER = 'User',
342
+ ACCOUNT = 'Account',
343
+ }
344
+ \`\`\`
345
+
346
+ After creating a dashboard, you should include the dashboard's url in your response to the user.`,
347
+ "create-inline-question-rule.md": `# JupiterOne Rule Creation Tool - Complete Guide
348
+
349
+ **Purpose**: Creates inline question-based alert rules in JupiterOne to monitor entities and trigger alerts based on specified conditions.
350
+
351
+ The first step in creating a rule is to identify the query you want to use in order to get the data you want to take action with. Use the \`execute-j1ql-query\` tool to find the correct query.
352
+
353
+ ## Key Requirements for Success
354
+
355
+ ### 1. Condition Format (Critical)
356
+
357
+ The \`condition\` parameter must use JupiterOne's specific array format:
358
+
359
+ - **Structure**: \`["LOGICAL_OPERATOR", [left_value, operator, right_value]]\`
360
+ - **Example**: \`["AND", ["queries.queryName.total", ">", 0]]\`
361
+ - **Supported operators**: \`>\`, \`<\`, \`>=\`, \`<=\`, \`=\`, \`!=\`
362
+ - **Logical operators**: \`"AND"\`, \`"OR"\`
363
+
364
+ ### 2. Operations Structure
365
+
366
+ The \`when\` clause should only contain:
367
+
368
+ - \`type\`: Always \`"FILTER"\`
369
+ - \`condition\`: The array format described above
370
+ - **Do NOT include**: \`version\`, \`specVersion\` (these belong at the rule level, not in the when clause)
371
+
372
+ ### 3. Query Naming Convention
373
+
374
+ - Query names in the \`queries\` array must match the references in conditions
375
+ - Example: If query name is \`"users"\`, reference it as \`"queries.users.total"\`
376
+ - **IMPORTANT**: Use \`"query0"\` as the standard query name for compatibility with existing patterns
377
+
378
+ ### 4. New Entity Detection
379
+
380
+ - Use \`triggerActionsOnNewEntitiesOnly: true\` to only alert on genuinely new entities
381
+ - This prevents re-alerting on existing entities every polling cycle
382
+ - Essential for "new user" or "new resource" type alerts
383
+
384
+ ### 5. Polling Intervals
385
+
386
+ - **Default**: Use \`"ONE_DAY"\` unless the user specifically requests a different interval
387
+ - **Available options**: \`"DISABLED"\`, \`"THIRTY_MINUTES"\`, \`"ONE_HOUR"\`, \`"FOUR_HOURS"\`, \`"EIGHT_HOURS"\`, \`"TWELVE_HOURS"\`, \`"ONE_DAY"\`, \`"ONE_WEEK"\`
388
+ - Only use more frequent intervals (like \`"THIRTY_MINUTES"\`) when explicitly requested or for time-sensitive security alerts
389
+
390
+ ### 6. Tags vs Labels (Important)
391
+
392
+ - **DEPRECATED**: The \`tags\` array field is deprecated and should always be set to an empty array \`[]\`
393
+ - **USE INSTEAD**: For tagging functionality, use the \`labels\` field with key-value pairs
394
+ - **Format**: \`labels: [{"labelName": "key", "labelValue": "value"}]\`
395
+ - **When users ask for tagging**: Always use the \`labels\` field to meet their needs
396
+ - **Note**: The \`tags\` field is still required in the schema for compatibility but should remain empty
397
+
398
+ ## Required Schema Fields
399
+
400
+ ### Complete Required Parameters for create-inline-question-rule
401
+
402
+ **CRITICAL**: All of these fields must be included for successful rule creation:
403
+
404
+ \`\`\`json
405
+ {
406
+ "name": "Rule Name",
407
+ "description": "Rule description",
408
+ "notifyOnFailure": true,
409
+ "triggerActionsOnNewEntitiesOnly": true,
410
+ "ignorePreviousResults": false,
411
+ "pollingInterval": "ONE_DAY",
412
+ "templates": {},
413
+ "outputs": ["alertLevel"],
414
+ "tags": [],
415
+ "labels": [
416
+ {"labelName": "environment", "labelValue": "production"},
417
+ {"labelName": "team", "labelValue": "security"}
418
+ ],
419
+ "queries": [
420
+ {
421
+ "query": "FIND Entity...",
422
+ "name": "query0",
423
+ "version": "v1",
424
+ "includeDeleted": false
425
+ }
426
+ ],
427
+ "operations": [
428
+ {
429
+ "when": {
430
+ "type": "FILTER",
431
+ "condition": ["AND", ["queries.query0.total", ">", 0]]
432
+ },
433
+ "actions": [...]
434
+ }
435
+ ]
436
+ }
437
+ \`\`\`
438
+
439
+ **Key Schema Requirements**:
440
+
441
+ - \`ignorePreviousResults\`: Must be included (typically \`false\`)
442
+ - \`templates\`: Must be included (use \`{}\` if empty)
443
+ - \`tags\`: Must be included but should always be empty \`[]\` (deprecated field)
444
+ - \`labels\`: Use this for actual tagging functionality with key-value pairs
445
+ - Query \`name\`: Use \`"query0"\` for primary query
446
+ - Query \`version\`: Include \`"v1"\` for compatibility
447
+ - Query \`includeDeleted\`: Must be explicitly set to \`false\`
448
+
449
+ ## Available Action Types
450
+
451
+ ### 1. SET_PROPERTY
452
+
453
+ Sets a property value on the alert (commonly used for alert severity levels).
454
+
455
+ **Configuration**:
456
+
457
+ \`\`\`json
458
+ {
459
+ "type": "SET_PROPERTY",
460
+ "targetProperty": "alertLevel",
461
+ "targetValue": "CRITICAL"
462
+ }
463
+ \`\`\`
464
+
465
+ **Common Values for alertLevel**: \`"LOW"\`, \`"MEDIUM"\`, \`"HIGH"\`, \`"CRITICAL"\`, \`"INFO"\`
466
+
467
+ ### 2. CREATE_ALERT
468
+
469
+ Creates a basic alert in JupiterOne.
470
+
471
+ **Configuration**:
472
+
473
+ \`\`\`json
474
+ {
475
+ "type": "CREATE_ALERT"
476
+ }
477
+ \`\`\`
478
+
479
+ **Note**: This is the most basic action and should almost always be included.
480
+
481
+ ### 3. SEND_EMAIL
482
+
483
+ Sends email notifications to specified recipients.
484
+
485
+ **Configuration**:
486
+
487
+ \`\`\`json
488
+ {
489
+ "type": "SEND_EMAIL",
490
+ "recipients": ["user1@company.com", "user2@company.com"],
491
+ "body": "Affected Items: <br><br>* {{queries.query0.data|mapProperty('displayName')|join('<br>* ')}}"
492
+ }
493
+ \`\`\`
494
+
495
+ **Required Information to Ask User**:
496
+
497
+ - Email addresses of recipients
498
+ - Custom email body content (if desired)
499
+
500
+ **Template Variables Available**:
501
+
502
+ - \`{{alertWebLink}}\` - Link to the alert in JupiterOne
503
+ - \`{{queries.queryName.data|mapProperty('fieldName')|join('separator')}}\` - Format query results
504
+
505
+ ### 4. TAG_ENTITIES
506
+
507
+ Adds or removes tags from entities that triggered the rule.
508
+
509
+ **Configuration**:
510
+
511
+ \`\`\`json
512
+ {
513
+ "type": "TAG_ENTITIES",
514
+ "entities": "{{queries.query0.data}}",
515
+ "tags": [
516
+ { "name": "existing tag to remove", "value": null },
517
+ { "name": "new tag", "value": "tag value" }
518
+ ]
519
+ }
520
+ \`\`\`
521
+
522
+ **Required Information to Ask User**:
523
+
524
+ - Tag names and values to add
525
+ - Tag names to remove (set value to \`null\`)
526
+
527
+ ### 5. SEND_SLACK_MESSAGE
528
+
529
+ Sends messages to Slack channels (requires Slack integration).
530
+
531
+ **Configuration**:
532
+
533
+ \`\`\`json
534
+ {
535
+ "integrationInstanceId": "d97d9127-c532-410a-bf0a-9ea93f66c3d2",
536
+ "type": "SEND_SLACK_MESSAGE",
537
+ "channels": ["#security-alerts", "#general"],
538
+ "body": "*Affected Items:* \n\n- {{queries.query0.data|mapProperty('displayName')|join('\n- ')}}"
539
+ }
540
+ \`\`\`
541
+
542
+ **Required Information to Ask User**:
543
+
544
+ - Slack channel names (with # prefix)
545
+ - Slack integration instance ID (may need to query available integrations)
546
+ - Custom message content (if desired)
547
+
548
+ ### 6. SEND_TO_S3
549
+
550
+ Sends alert data to an S3 bucket (requires AWS S3 integration).
551
+
552
+ **Configuration**:
553
+
554
+ \`\`\`json
555
+ {
556
+ "integrationInstanceId": "f89568b4-2a1b-4bd8-8abd-aee21270df75",
557
+ "type": "SEND_TO_S3",
558
+ "bucket": "security-alerts-bucket",
559
+ "region": "us-east-1",
560
+ "data": {
561
+ "description": "{{alertWebLink}}\n\n**Affected Items:**\n\n* {{queries.query0.data|mapProperty('displayName')|join('\n* ')}}"
562
+ }
563
+ }
564
+ \`\`\`
565
+
566
+ **Required Information to Ask User**:
567
+
568
+ - S3 bucket name
569
+ - AWS region
570
+ - S3 integration instance ID
571
+ - Data structure to send
572
+
573
+ ### 7. CREATE_JIRA_TICKET
574
+
575
+ Creates a Jira ticket for the alert (requires Jira integration).
576
+
577
+ **Configuration**:
578
+
579
+ \`\`\`json
580
+ {
581
+ "integrationInstanceId": "53a99eaa-18a5-45ef-b748-2de39d642a91",
582
+ "type": "CREATE_JIRA_TICKET",
583
+ "entityClass": "Finding",
584
+ "summary": "Security Alert: Critical Unencrypted Data Found",
585
+ "issueType": "Bug",
586
+ "project": "SEC",
587
+ "updateContentOnChanges": false,
588
+ "additionalFields": {
589
+ "description": {
590
+ "type": "doc",
591
+ "version": 1,
592
+ "content": [
593
+ {
594
+ "type": "paragraph",
595
+ "content": [
596
+ {
597
+ "type": "text",
598
+ "text": "{{alertWebLink}}\n\n**Affected Items:**\n\n* {{queries.query0.data|mapProperty('displayName')|join('\n* ')}}"
599
+ }
600
+ ]
601
+ }
602
+ ]
603
+ }
604
+ }
605
+ }
606
+ \`\`\`
607
+
608
+ **Required Information to Ask User**:
609
+
610
+ - Jira project key
611
+ - Issue type (Bug, Task, Story, etc.)
612
+ - Ticket summary/title
613
+ - Jira integration instance ID
614
+ - Additional fields as needed
615
+
616
+ **Common Entity Classes**: \`"Finding"\`, \`"Incident"\`, \`"Issue"\`
617
+
618
+ ## Template Variables and Formatting
619
+
620
+ ### Available Variables
621
+
622
+ - \`{{alertWebLink}}\` - Direct link to the alert in JupiterOne
623
+ - \`{{queries.queryName.data}}\` - Array of entities from the specified query
624
+ - \`{{queries.queryName.total}}\` - Count of entities from the query
625
+
626
+ ### Data Formatting
627
+
628
+ - \`|mapProperty('fieldName')\` - Extract specific field from each entity
629
+ - \`|join('separator')\` - Join array elements with specified separator
630
+ - Example: \`{{queries.users.data|mapProperty('displayName')|join(', ')}}\` - Creates comma-separated list of user names
631
+
632
+ ### Common Formatting Patterns
633
+
634
+ - **HTML list**: \`{{queries.query0.data|mapProperty('displayName')|join('<br>* ')}}\`
635
+ - **Markdown list**: \`{{queries.query0.data|mapProperty('displayName')|join('\n- ')}}\`
636
+ - **Simple list**: \`{{queries.query0.data|mapProperty('displayName')|join('\n* ')}}\`
637
+
638
+ ## Integration Dependencies
639
+
640
+ For actions requiring integrations, you may need to:
641
+
642
+ 1. Query available integration instances using \`get-integration-instances\`
643
+ 2. Ask the user which integration to use
644
+ 3. Use the integration's \`id\` as the \`integrationInstanceId\`
645
+
646
+ **Actions requiring integrations**:
647
+
648
+ - \`SEND_SLACK_MESSAGE\` (Slack integration)
649
+ - \`SEND_TO_S3\` (AWS S3 integration)
650
+ - \`CREATE_JIRA_TICKET\` (Jira integration)
651
+
652
+ ## Working Example Template
653
+
654
+ ### Complete Working Rule Structure
655
+
656
+ Based on confirmed working examples, use this template:
657
+
658
+ \`\`\`json
659
+ {
660
+ "name": "Your Rule Name",
661
+ "description": "Your rule description",
662
+ "notifyOnFailure": true,
663
+ "triggerActionsOnNewEntitiesOnly": true,
664
+ "ignorePreviousResults": false,
665
+ "pollingInterval": "ONE_DAY",
666
+ "templates": {},
667
+ "outputs": ["alertLevel"],
668
+ "tags": [],
669
+ "labels": [
670
+ { "labelName": "severity", "labelValue": "high" },
671
+ { "labelName": "category", "labelValue": "security" }
672
+ ],
673
+ "question": {
674
+ "queries": [
675
+ {
676
+ "query": "FIND Entity WITH condition",
677
+ "name": "query0",
678
+ "version": "v1",
679
+ "includeDeleted": false
680
+ }
681
+ ]
682
+ },
683
+ "operations": [
684
+ {
685
+ "when": {
686
+ "type": "FILTER",
687
+ "condition": ["AND", ["queries.query0.total", ">", 0]]
688
+ },
689
+ "actions": [
690
+ {
691
+ "type": "SET_PROPERTY",
692
+ "targetProperty": "alertLevel",
693
+ "targetValue": "CRITICAL"
694
+ },
695
+ {
696
+ "type": "CREATE_ALERT"
697
+ },
698
+ {
699
+ "type": "SEND_EMAIL",
700
+ "recipients": ["user@company.com"],
701
+ "body": "Affected Items: <br><br>* {{queries.query0.data|mapProperty('displayName')|join('<br>* ')}}"
702
+ }
703
+ ]
704
+ }
705
+ ]
706
+ }
707
+ \`\`\`
708
+
709
+ ## Common Patterns
710
+
711
+ ### New Entity Monitoring
712
+
713
+ \`\`\`json
714
+ {
715
+ "condition": ["AND", ["queries.query0.total", ">", 0]],
716
+ "triggerActionsOnNewEntitiesOnly": true
717
+ }
718
+ \`\`\`
719
+
720
+ ### Threshold-based Alerts
721
+
722
+ \`\`\`json
723
+ {
724
+ "condition": ["AND", ["queries.query0.total", ">=", 5]]
725
+ }
726
+ \`\`\`
727
+
728
+ ### Multi-action Rule Example
729
+
730
+ \`\`\`json
731
+ "actions": [
732
+ {"type": "SET_PROPERTY", "targetProperty": "alertLevel", "targetValue": "HIGH"},
733
+ {"type": "CREATE_ALERT"},
734
+ {"type": "SEND_EMAIL", "recipients": ["security@company.com"], "body": "Security issue detected: {{alertWebLink}}"},
735
+ {"type": "TAG_ENTITIES", "entities": "{{queries.query0.data}}", "tags": [{"name": "needs-review", "value": "true"}]}
736
+ ]
737
+ \`\`\`
738
+
739
+ ## Debugging Tips
740
+
741
+ - If you get "Invalid conjunction operator" errors, check the condition array format
742
+ - If you get "additional properties" errors, remove extra fields from the \`when\` clause
743
+ - If you get missing property errors, ensure all required schema fields are included
744
+ - **Always include**: \`ignorePreviousResults\`, \`templates\`, \`tags\`, query \`version\` and \`includeDeleted\`
745
+ - Always reference existing rules with \`get-rule-details\` to see working examples
746
+ - Test with simple conditions first, then add complexity
747
+ - Use \`"query0"\` as the standard query name for compatibility
748
+
749
+ ## Best Practices
750
+
751
+ - Use descriptive query names that match their purpose (but prefer \`"query0"\` for main query)
752
+ - Include relevant entity fields in \`outputs\` for alert context
753
+ - Set appropriate polling intervals (default to \`"ONE_DAY"\` unless specified)
754
+ - Use the \`labels\` field for rule organization and tagging (not the deprecated \`tags\` field)
755
+ - Use \`notifyOnFailure: true\` to catch rule execution issues
756
+ - Always include \`CREATE_ALERT\` action as a baseline
757
+ - Always include all required schema fields from the working template
758
+ - Ask users for specific details when configuring notification actions (emails, channels, etc.)
759
+ - When users request tagging functionality, use the \`labels\` field with key-value pairs
760
+
761
+ This format ensures reliable rule creation and helps avoid common pitfalls encountered during rule development.
762
+ After creating a rule, you should include the rule's url in your message to the user.
763
+ `,
764
+ "create-j1ql-from-natural-language.md": `# JupiterOne Natural Language to J1QL Converter
765
+
766
+ **Purpose**: Converts natural language queries into JupiterOne Query Language (J1QL) syntax using AI-powered translation.
767
+ Unless the user gives a specific query to run, this should always be used for determing a query to use for any (but not exclusively) of the following:
768
+ - Queries for rules
769
+ - Queries for widgets
770
+ - Queries to answer a user's question regarding their data in jupiterone`,
771
+ "evaluate-rule.md": `# Evaluate Rule Tool
772
+
773
+ Manually trigger the evaluation of a JupiterOne alert rule. This tool forces an immediate evaluation of the rule's conditions and returns the results.
774
+
775
+ ## Parameters
776
+ - \`ruleId\` (required): The unique identifier of the rule to evaluate
777
+
778
+ ## Example Usage
779
+ Evaluate a specific rule:
780
+ \`\`\`json
781
+ {
782
+ "ruleId": "12345678-1234-1234-1234-123456789abc"
783
+ }
784
+ \`\`\``,
785
+ "execute-j1ql-query.md": `# JupiterOne J1QL Query Executor
786
+
787
+ **Purpose**: Executes JupiterOne Query Language (J1QL) queries against your JupiterOne data and returns the results. This tool is used to directly run J1QL queries that have been created, either manually or through the natural language converter.
788
+
789
+ This tool should be used when:
790
+ - You need to validate the data of a query
791
+ - You need to get results from a previously generated query
792
+ - You want to test a query before using it in a rule or widget
793
+ - You need to analyze data directly using J1QL
794
+
795
+ The tool supports various query parameters including:
796
+ - Including/excluding deleted entities
797
+ - Returning row metadata
798
+ - Returning computed properties
799
+ - Applying scope filters
800
+ - Pagination using cursors
801
+
802
+ ### JupiterOne Query Language (J1QL) Quick Reference
803
+
804
+ > **IMPORTANT:** Always validate queries using this tool before creating rules or widgets. Start with discovery queries if unsure about data structure.
805
+
806
+ #### Core Concepts
807
+
808
+ **Entity and Relationship Structure**
809
+ - **Entities**: Assets in your environment with specific classes and types
810
+ - **Entity Class**: Always \`TitleCase\` (e.g., \`User\`, \`Host\`, \`Application\`)
811
+ - **Entity Type**: Always \`snake_case\` (e.g., \`aws_iam_user\`, \`github_user\`)
812
+ - **Relationships**: Connections between entities
813
+ - **Relationship Class**: Always \`ALLCAPS\` (e.g., \`HAS\`, \`USES\`, \`PROTECTS\`)
814
+ - **Default Returns**: Queries return the first entity after FIND unless explicitly modified with RETURN
815
+ - **Unified Entities**: Deduplicated repersentation of assets seen in JupiterOne have a \`_type: unified_entity\`
816
+
817
+ #### Unified Entities
818
+
819
+ Unified entities are the deduplicated "real-world" repersentation of data seen by JupiterOne. All Unified entities have a \`_type = unified_entity\`, and this is often the entity the user wants referenced.
820
+
821
+ Unified Entities currently supported:
822
+ - **UnifiedDevice**: Deduplicated representation of devices in the inventory
823
+ - **UnifiedIdentity**: Deduplicated representation of identities in the inventory
824
+ - **UnifiedVulnerability**: Deduplicated representation of vulnerabilities in the inventory
825
+
826
+ Unified entities typically also have additional enrichment making them valuable assets to search off of or reference back to. Unified entities only have relationships to the entities that they deduplicate, and you need to query off of their source components to get more context - for example a list of all devices related to users would look like:
827
+
828
+ \`\`\`
829
+ FIND UnifiedIdentity AS identity
830
+ THAT IS << User
831
+ THAT RELATES TO AS rel (Device|Host)
832
+ THAT IS >> UnifiedDevice AS device
833
+ RETURN identity.displayName, rel._class, device.displayName
834
+ \`\`\`
835
+
836
+ **IMPORTANT**: Whenever answering questions about entities that have a unified entity representation, answer the question in terms of unified entities.
837
+
838
+ #### MANDATORY Query Structure
839
+
840
+ \`\`\`
841
+ FIND <entity> [WITH <property_filter>] [AS <alias>]
842
+ [THAT <relationship> [<direction>] <entity> [WITH <property_filter>] [AS <alias>]]
843
+ [WHERE <condition>]
844
+ [RETURN <field_selection>]
845
+ [ORDER BY <field>]
846
+ [SKIP <number>]
847
+ [LIMIT <number>]
848
+ \`\`\`
849
+
850
+ #### ⚠️ CRITICAL SYNTAX RULES ⚠️ ALL QUERIES MUST ADHERE TO THESE RULES
851
+
852
+ 1. **Alias Placement**: Aliases MUST follow the WITH statement when filtering
853
+ ✅ \`FIND Device WITH name~='TEST' AS dev\`
854
+ ❌ \`FIND Device AS dev WITH name~='TEST'\`
855
+
856
+ 2. **String Values**: ALWAYS use single quotes for strings, NEVER double quotes
857
+ ✅ \`name ~= 'john'\`
858
+ ❌ \`name ~= "john"\`
859
+
860
+ 3. **WITH vs WHERE**: Use WITH for entity properties, WHERE only for relationship properties or cross-entity comparisons
861
+ ✅ \`FIND User WITH active = true\`
862
+ ✅ \`FIND User AS u THAT HAS Device AS d WHERE u.active = true AND d.platform = 'darwin'\`
863
+ ❌ \`FIND User WHERE active = true\`
864
+
865
+ 4. **LIMIT Usage**: ALWAYS include LIMIT (5-100) or use COUNT for discovery
866
+ ✅ \`FIND User LIMIT 50\`
867
+ ✅ \`FIND User AS u RETURN u._type, count(u)\`
868
+ ❌ \`FIND User\` (no limit specified)
869
+
870
+ 5. **Relationship Direction**: Direction arrows MUST follow the relationship verb
871
+ ✅ \`FIND User THAT HAS >> Device\`
872
+ ❌ \`FIND User THAT >> HAS Device\`
873
+
874
+ 6. **Optional Traversals**: Use parentheses and question mark
875
+ ✅ \`FIND User AS u (THAT IS Person AS p)?\`
876
+ ❌ \`FIND User AS u THAT IS? Person AS p\`
877
+
878
+ 7. **Using Aggregates For Discovery**: Alias COUNT and use ORDER BY
879
+ ✅ \`FIND * AS ent RETURN ent._class, COUNT(ent) AS cnt ORDER BY cnt DESC LIMIT 50\`
880
+ ❌ \`FIND * AS ent RETURN ent._class, COUNT(ent) LIMIT 50\`
881
+
882
+ #### Entity Selection
883
+
884
+ **Finding by class or type**:
885
+ \`\`\`j1ql
886
+ FIND User LIMIT 10 # Find entities with _class = 'User'
887
+ FIND aws_iam_user LIMIT 10 # Find entities with _type = 'aws_iam_user'
888
+ FIND * WITH _type='aws_instance' LIMIT 10 # Filter any entity by type
889
+ \`\`\`
890
+
891
+ **Finding multiple entity types**:
892
+ \`\`\`j1ql
893
+ FIND (User | Host) LIMIT 10 # Find entities with _class = 'User' OR _class = 'Host'
894
+ \`\`\`
895
+
896
+ #### Property Filtering (WITH)
897
+
898
+ **Basic property filtering**:
899
+ \`\`\`j1ql
900
+ FIND User WITH active = true LIMIT 10
901
+ FIND DataStore WITH encrypted = false LIMIT 10
902
+ \`\`\`
903
+
904
+ **WITH filtering with alias** (CORRECT ORDER):
905
+ \`\`\`j1ql
906
+ FIND User WITH active = true AS u LIMIT 10
907
+ FIND DataStore WITH encrypted = false AS ds LIMIT 10
908
+ \`\`\`
909
+
910
+ **WITH filtering with alias AND Advanced fiiltering** (CORRECT ORDER):
911
+ \`\`\`j1ql
912
+ FIND User WITH accountCount > 0 AS u RETURN u.displayName
913
+ FIND DataStore WITH name~='ROOT' OR name=/iam/i AS ds RETURN ds.name, ds.encrypted LIMIT 10
914
+ \`\`\`
915
+
916
+ **Multiple property filters**:
917
+ \`\`\`j1ql
918
+ FIND User WITH active = true AND mfaEnabled = false LIMIT 10
919
+ FIND Host WITH platform = 'darwin' OR platform = 'linux' LIMIT 10
920
+ \`\`\`
921
+
922
+ **Multiple value matching**:
923
+ \`\`\`j1ql
924
+ FIND Host WITH platform = ('darwin' OR 'linux') LIMIT 10
925
+ \`\`\`
926
+
927
+ **Property existence check**:
928
+ \`\`\`j1ql
929
+ FIND DataStore WITH encrypted = undefined LIMIT 10
930
+ \`\`\`
931
+
932
+ **Special character property names**:
933
+ \`\`\`j1ql
934
+ FIND Host WITH [tag.special-name] = 'value' LIMIT 10
935
+ \`\`\`
936
+
937
+ #### String Comparisons
938
+
939
+ J1QL comparison operators:
940
+ - \`=\` : equals (exact match)
941
+ - \`!=\` : not equals
942
+ - \`~=\` : contains
943
+ - \`^=\` : starts with
944
+ - \`$=\` : ends with
945
+ - \`!~=\` : does not contain
946
+ - \`!^=\` : does not start with
947
+ - \`!$=\` : does not end with
948
+
949
+ \`\`\`j1ql
950
+ FIND User WITH username ~= 'john' LIMIT 10
951
+ FIND Host WITH name ^= 'web' LIMIT 10
952
+ \`\`\`
953
+
954
+ #### Case-Insensitive Matching (Regex)
955
+
956
+ \`\`\`j1ql
957
+ FIND User WITH username=/john/ LIMIT 10 # Case-insensitive match
958
+ \`\`\`
959
+
960
+ #### Traversing Relationships (THAT)
961
+
962
+ ## Important: Don't assume relationship VERBS, either do discovery to determine the correct relationship or use the wild card relationship "THAT RELATES TO"
963
+
964
+ **Any relationship traversal (i.e. wildcard)**:
965
+ \`\`\`j1ql
966
+ FIND User THAT RELATES TO Application LIMIT 10
967
+ \`\`\`
968
+
969
+ **Basic traversal**:
970
+ \`\`\`j1ql
971
+ FIND User THAT HAS Device LIMIT 10
972
+ \`\`\`
973
+
974
+ **Multiple traversal steps**:
975
+ \`\`\`j1ql
976
+ FIND User THAT HAS Device THAT INSTALLED Application LIMIT 10
977
+ \`\`\`
978
+
979
+ **Multi-step traversal with filtering**:
980
+ \`\`\`j1ql
981
+ FIND User WITH active = true THAT HAS Device THAT INSTALLED Application WITH vendor = 'Microsoft' LIMIT 10
982
+ \`\`\`
983
+
984
+ **Multiple relationship types**:
985
+ \`\`\`j1ql
986
+ FIND HostAgent THAT (MONITORS|PROTECTS) Host LIMIT 10
987
+ \`\`\`
988
+
989
+ **Negating relationships**:
990
+ \`\`\`j1ql
991
+ FIND User THAT !HAS Device LIMIT 10 # Find users that don't have devices
992
+ \`\`\`
993
+
994
+ **Relationship direction** (arrows MUST follow relationship):
995
+ \`\`\`j1ql
996
+ FIND User THAT HAS >> Device LIMIT 10 # Direction from User to Device
997
+ FIND Device THAT HAS << User LIMIT 10 # Direction from User to Device
998
+ \`\`\`
999
+
1000
+ #### Using Aliases (AS) - ALWAYS AFTER WITH CLAUSE
1001
+
1002
+ \`\`\`j1ql
1003
+ FIND User WITH active = true AS u
1004
+ THAT HAS AS relationship Device WITH platform = 'darwin' AS d
1005
+ RETURN u._type, relationship._class, d._type, COUNT(relationship)
1006
+ LIMIT 10
1007
+ \`\`\`
1008
+
1009
+ #### Post-Traversal Filtering (WHERE) - ONLY FOR RELATIONSHIPS OR CROSS-ENTITY COMPARISON
1010
+
1011
+ **Example of filtering on relationship properties**
1012
+ \`\`\`j1ql
1013
+ FIND Firewall AS fw
1014
+ THAT ALLOWS AS rule * AS n
1015
+ WHERE rule.ingress = true
1016
+ LIMIT 10
1017
+ \`\`\`
1018
+
1019
+ \`\`\`j1ql
1020
+ FIND User AS u
1021
+ THAT HAS Device AS d
1022
+ WHERE u.active = true AND d.platform = 'darwin'
1023
+ LIMIT 10
1024
+ \`\`\`
1025
+
1026
+ #### Selecting Return Values (RETURN)
1027
+
1028
+ \`\`\`j1ql
1029
+ FIND User AS u
1030
+ THAT HAS Device AS d
1031
+ RETURN u.username, d.name
1032
+ LIMIT 10
1033
+ \`\`\`
1034
+
1035
+ Return all properties:
1036
+ \`\`\`j1ql
1037
+ FIND User AS u RETURN u.* LIMIT 10
1038
+ \`\`\`
1039
+
1040
+ #### Aggregation Functions (USE FOR DISCOVERY)
1041
+
1042
+ Available aggregations:
1043
+ - \`count(selector)\`
1044
+ - \`min(selector.field)\`
1045
+ - \`max(selector.field)\`
1046
+ - \`avg(selector.field)\`
1047
+ - \`sum(selector.field)\`
1048
+
1049
+ \`\`\`j1ql
1050
+ # Basic count
1051
+ FIND User AS u RETURN count(u)
1052
+
1053
+ # Group by with count
1054
+ FIND User AS u RETURN u._type, count(u)
1055
+
1056
+ # Multiple aggregations
1057
+ FIND Account AS acct THAT HAS User AS user
1058
+ RETURN acct.name, count(user), avg(user.lastLoginOn)
1059
+ \`\`\`
1060
+
1061
+ #### Date Comparisons
1062
+
1063
+ \`\`\`j1ql
1064
+ FIND User WITH createdOn > date.now - 7 days LIMIT 10
1065
+ \`\`\`
1066
+
1067
+ Supported units: \`hour(s)\`, \`day(s)\`, \`month(s)\`, \`year(s)\`
1068
+
1069
+ #### Math Operations
1070
+
1071
+ \`\`\`j1ql
1072
+ FIND aws_instance AS i
1073
+ RETURN i.name, i.memorySize * 0.001 AS memoryGB
1074
+ LIMIT 10
1075
+ \`\`\`
1076
+
1077
+ #### Sorting and Pagination
1078
+
1079
+ \`\`\`j1ql
1080
+ FIND User AS u
1081
+ ORDER BY u.username
1082
+ SKIP 10
1083
+ LIMIT 5
1084
+ \`\`\`
1085
+
1086
+ #### Optional Traversals (PROPER SYNTAX)
1087
+
1088
+ \`\`\`j1ql
1089
+ FIND User AS u
1090
+ (THAT IS Person AS p)?
1091
+ THAT HAS Device AS d
1092
+ LIMIT 10
1093
+ \`\`\`
1094
+
1095
+ Optional traversal with property access:
1096
+ \`\`\`j1ql
1097
+ FIND User AS u
1098
+ (THAT IS Person AS p)?
1099
+ THAT HAS Device AS d
1100
+ RETURN u.username, p.email, d.name
1101
+ LIMIT 10
1102
+ \`\`\`
1103
+
1104
+ #### Discovery Queries - ALWAYS START HERE
1105
+
1106
+ 1. **Find all entity classes**: \`FIND * AS e RETURN e._class, COUNT(e)\`
1107
+ 2. **Explore entity properties**: \`FIND EntityClass AS e RETURN e.* LIMIT 10\`
1108
+ 3. **Discover relationships**: \`FIND Entity1 THAT RELATES TO AS rel Entity2 RETURN rel._class\`
1109
+ 4. **Check property values**: \`FIND Entity AS e RETURN e.property, COUNT(e)\`
1110
+
1111
+ #### ⚠️ QUERY VALIDATION CHECKLIST ⚠️
1112
+
1113
+ Before running any J1QL query, verify:
1114
+
1115
+ 1. ✓ FIND statement specifies entity class or type
1116
+ 2. ✓ All string values use single quotes, not double quotes
1117
+ 3. ✓ Aliases are placed AFTER the WITH statement
1118
+ 4. ✓ All queries include either LIMIT or use COUNT aggregation
1119
+ 5. ✓ WITH is used for entity properties, WHERE only for relationship properties or cross-entity comparisons
1120
+ 6. ✓ Direction arrows (>> or <<) are placed after relationship verbs
1121
+ 7. ✓ Optional traversals use proper parentheses and question mark syntax
1122
+ 8. ✓ All aliases referenced in RETURN or WHERE are properly defined earlier
1123
+
1124
+ #### Most Common Errors (Quick Reference)
1125
+
1126
+ 1. **Missing quotes**: \`name = john\` → \`name = 'john'\`
1127
+ 2. **Wrong quotes**: \`name = "john"\` → \`name = 'john'\`
1128
+ 3. **Alias placement**: \`AS u WITH active = true\` → \`WITH active = true AS u\`
1129
+ 4. **WHERE needs alias**: \`WHERE active = true\` → \`AS u WHERE u.active = true\`
1130
+ 5. **Undefined alias**: \`FIND User RETURN u.name\` → \`FIND User AS u RETURN u.name\`
1131
+ 6. **No LIMIT**: Add \`LIMIT 100\` or use \`COUNT()\` to prevent timeouts
1132
+
1133
+ #### Common Patterns & Examples
1134
+
1135
+ **Security Queries**:
1136
+ - Unencrypted data: \`FIND DataStore WITH encrypted = false\`
1137
+ - Users without MFA: \`FIND User WITH mfaEnabled != true\`
1138
+ - Critical findings: \`FIND Finding WITH severity = "critical"\`
1139
+
1140
+ **Dashboard Queries**:
1141
+ - Pie chart: Return \`name\` and \`value\` pairs
1142
+ - Number chart: Return single \`value\`
1143
+ - Bar chart: Return \`x\` and \`y\` values
1144
+ - Table: Return named columns
1145
+
1146
+ **Rule Queries**:
1147
+ - New entities: Add time filter \`WITH _createdOn > date.now - 1 day\`
1148
+ - Always test with \`execute-j1ql-query\` first
1149
+ - Use condition: \`["AND", ["queries.query0.total", ">", 0]]\`
1150
+
1151
+ #### Best Practices
1152
+
1153
+ 1. **Always start with discovery** - Don't assume entity names or properties
1154
+ 2. **Test incrementally** - Build complex queries step by step
1155
+ 3. **Use this tool to validate** - Test every query before using in rules/widgets
1156
+ 4. **Check error suggestions** - The tool provides specific fixes for common issues
1157
+ 5. **Use proper syntax**:
1158
+ - Single quotes for strings
1159
+ - Alias AFTER WITH clause
1160
+ - LIMIT to prevent timeouts
1161
+ - Proper capitalization for classes
1162
+
1163
+ **Remember**: The execute-j1ql-query tool now provides enhanced error messages with specific suggestions. Always test queries here first!`,
1164
+ "get-dashboard-details.md": `# Get Dashboard Details Tool
1165
+
1166
+ Get detailed information about a specific JupiterOne dashboard including its widgets, layout, and configuration.
1167
+
1168
+ ## Parameters
1169
+ - \`dashboardId\` (required): The unique identifier of the dashboard to retrieve
1170
+
1171
+ ## Example Usage
1172
+ Get details of a specific dashboard:
1173
+ \`\`\`json
1174
+ {
1175
+ "dashboardId": "95936c1a-468a-494f-b11d-b134ac9b9577"
1176
+ }
1177
+ \`\`\``,
1178
+ "get-dashboards.md": `# Get Dashboards Tool
1179
+
1180
+ List all dashboards available in your JupiterOne account. This tool returns both personal and account-level dashboards with their metadata.
1181
+
1182
+ ## Parameters
1183
+ None required.
1184
+
1185
+ ## Example Usage
1186
+ Get all dashboards:
1187
+ \`\`\`json
1188
+ {}
1189
+ \`\`\``,
1190
+ "get-integration-definitions.md": `# Get Integration Definitions Tool
1191
+
1192
+ Get all available integration definitions in your JupiterOne account. This tool returns a list of integration definitions that can be used to create integration instances. Integration definitions define the types of integrations available (like AWS, Azure, GitHub, etc.) and their configuration requirements. If a user is needing a specific integration instance id for something such as a rule action, you will want to start here and then use the \`get-integration-instances\` tool. Each integration definition will have a Name and a Title field, you should use this to identify which definition is correct for what the user is looking for. As an example, if the user wants to send a slack notification as a part of a rule action, you would want to pull all of the integration definitions and find any that have Slack in the name and/or title. If there are multiple, then clarify the differences to the user and allow them to guide you on which one is correct.
1193
+
1194
+ ## Parameters
1195
+ - \`cursor\` (optional): Pagination cursor to get the next page of results. Use the \`endCursor\` from a previous response's \`pageInfo\`. When you are needing to find a specific type of integration, you will want to query all of the available pages until there are no more left to query so you can select from the entire list.
1196
+ - \`includeConfig\` (optional): Whether to include configuration fields in the response. When true, returns detailed configuration schemas for each integration type. Typically this should be false or omitted entirely.
1197
+
1198
+ ## Example Usage
1199
+ Get all integration definitions without configuration details:
1200
+ \`\`\`json
1201
+ {}
1202
+ \`\`\`
1203
+
1204
+ Get all integration definitions with configuration fields:
1205
+ \`\`\`json
1206
+ {
1207
+ "includeConfig": true
1208
+ }
1209
+ \`\`\`
1210
+
1211
+ Get the next page of integration definitions using a cursor:
1212
+ \`\`\`json
1213
+ {
1214
+ "cursor": "cursor_here"
1215
+ }
1216
+ \`\`\``,
1217
+ "get-integration-events.md": `# Get Integration Events Tool
1218
+
1219
+ Get events and logs from a specific integration job execution. This tool provides detailed execution logs for troubleshooting integration issues.
1220
+
1221
+ ## Parameters
1222
+ - \`jobId\` (required): The ID of the job to get events for
1223
+ - \`integrationInstanceId\` (required): The ID of the instance the job belongs to
1224
+ - \`size\` (optional): Maximum number of events to return (1-1000)
1225
+ - \`cursor\` (optional): Pagination cursor for fetching additional events
1226
+
1227
+ ## Example Usage
1228
+ Get events for a specific job:
1229
+ \`\`\`json
1230
+ {
1231
+ "jobId": "job-123",
1232
+ "integrationInstanceId": "instance-456",
1233
+ "size": 50
1234
+ }
1235
+ \`\`\``,
1236
+ "get-integration-instances.md": `# Get Integration Instances Tool
1237
+
1238
+ Get all integration instances in your JupiterOne account. This tool returns a list of configured integration instances, including their configuration, status, and recent job information. Integration instances are the actual configured connections to external services like AWS accounts, GitHub repositories, etc. Unless you have an integration definition id, you typically will not want to query this yet. To get an integration definition id, use the \`get-integration-definitions\` tool. If you need an integration instance id for another task (such as creating a rule action), ask the user which of the possible integrations they want you to use.
1239
+
1240
+ ## Parameters
1241
+ - \`definitionId\` (optional): Filter instances by a specific integration definition ID. Use this to get only instances of a particular integration type.
1242
+ - \`limit\` (optional): Maximum number of instances to return (between 1 and 1000).
1243
+
1244
+ ## Example Usage
1245
+ Get all integration instances:
1246
+ \`\`\`json
1247
+ {}
1248
+ \`\`\`
1249
+
1250
+ Get the first 10 integration instances:
1251
+ \`\`\`json
1252
+ {
1253
+ "limit": 10
1254
+ }
1255
+ \`\`\`
1256
+
1257
+ Get all instances of a specific integration type:
1258
+ \`\`\`json
1259
+ {
1260
+ "definitionId": "integration-definition-id-here"
1261
+ }
1262
+ \`\`\`
1263
+
1264
+ Get the first 5 instances of a specific integration type:
1265
+ \`\`\`json
1266
+ {
1267
+ "definitionId": "integration-definition-id-here",
1268
+ "limit": 5
1269
+ }
1270
+ \`\`\``,
1271
+ "get-integration-job.md": `# Get Integration Job Tool
1272
+
1273
+ Get detailed information about a specific integration job execution.
1274
+
1275
+ ## Parameters
1276
+ - \`integrationJobId\` (required): The ID of the job to retrieve
1277
+ - \`integrationInstanceId\` (required): The ID of the instance the job belongs to
1278
+
1279
+ ## Example Usage
1280
+ Get details of a specific integration job:
1281
+ \`\`\`json
1282
+ {
1283
+ "integrationJobId": "job-123",
1284
+ "integrationInstanceId": "instance-456"
1285
+ }
1286
+ \`\`\``,
1287
+ "get-integration-jobs.md": `# Get Integration Jobs Tool
1288
+
1289
+ List integration job execution history. This tool returns information about integration runs including their status, timing, and results.
1290
+
1291
+ ## Parameters
1292
+ - \`integrationDefinitionId\` (optional): Filter jobs by definition ID
1293
+ - \`integrationInstanceId\` (optional): Filter jobs by instance ID
1294
+ - \`integrationInstanceIds\` (optional): Array of instance IDs to filter jobs
1295
+ - \`status\` (optional): Filter by job status (PENDING, RUNNING, COMPLETED, FAILED, CANCELLED)
1296
+ - \`size\` (optional): Maximum number of jobs to return (1-1000)
1297
+
1298
+ ## Example Usage
1299
+ Get all integration jobs:
1300
+ \`\`\`json
1301
+ {}
1302
+ \`\`\`
1303
+
1304
+ Get jobs for a specific integration instance:
1305
+ \`\`\`json
1306
+ {
1307
+ "integrationInstanceId": "abc123",
1308
+ "status": "FAILED",
1309
+ "size": 10
1310
+ }
1311
+ \`\`\``,
1312
+ "get-raw-data-download-url.md": `# Get Raw Data Download URL Tool
1313
+
1314
+ Generate a signed URL for downloading raw data from JupiterOne. This is typically used to download large result sets from rule evaluations.
1315
+
1316
+ ## Parameters
1317
+ - \`rawDataKey\` (required): The key identifying the raw data to download
1318
+
1319
+ ## Example Usage
1320
+ Get download URL for raw data:
1321
+ \`\`\`json
1322
+ {
1323
+ "rawDataKey": "data-key-123"
1324
+ }
1325
+ \`\`\``,
1326
+ "get-rule-details.md": `# Get Rule Details Tool
1327
+
1328
+ Get detailed information about a specific JupiterOne alert rule by its ID. This tool returns comprehensive rule configuration including queries, conditions, actions, and metadata.
1329
+
1330
+ ## Parameters
1331
+ - \`ruleId\` (required): The unique identifier of the rule to retrieve
1332
+
1333
+ ## Example Usage
1334
+ Request the details of a specific rule:
1335
+ \`\`\`json
1336
+ {
1337
+ "ruleId": "12345678-1234-1234-1234-123456789abc"
1338
+ }
1339
+ \`\`\``,
1340
+ "get-rule-evaluation-details.md": `# Get Rule Evaluation Details Tool
1341
+
1342
+ Get detailed information about a specific rule evaluation including query results and any generated alerts.
1343
+
1344
+ ## Parameters
1345
+ - \`ruleId\` (required): The ID of the rule
1346
+ - \`timestamp\` (required): The timestamp of the evaluation to retrieve (Unix timestamp)
1347
+
1348
+ ## Example Usage
1349
+ Get details of a specific rule evaluation:
1350
+ \`\`\`json
1351
+ {
1352
+ "ruleId": "rule-123",
1353
+ "timestamp": 1641024000000
1354
+ }
1355
+ \`\`\``,
1356
+ "get-rule-evaluation-query-results.md": `# Get Rule Evaluation Query Results Tool
1357
+
1358
+ Retrieve the actual query results from a rule evaluation. This tool fetches the entities that matched the rule's query conditions.
1359
+
1360
+ ## Parameters
1361
+ - \`rawDataKey\` (required): The key identifying the query results to retrieve
1362
+
1363
+ ## Example Usage
1364
+ Get query results from a rule evaluation:
1365
+ \`\`\`json
1366
+ {
1367
+ "rawDataKey": "results-key-123"
1368
+ }
1369
+ \`\`\``,
1370
+ "list-alerts.md": `# List Alerts Tool
1371
+
1372
+ List all currently active alerts in your JupiterOne account. This tool returns a list of active alert instances, including their IDs, names, descriptions, levels, statuses, timestamps, and related rule information. You can optionally specify a limit to restrict the number of alerts returned. If a user is looking for configuration behind an alert, then list out the rules or get the details of the rule associated with an alert. If they are looking for alert data or then use this tool rather than listing rules.
1373
+
1374
+ ## Parameters
1375
+ - \`limit\` (optional): Maximum number of alerts to return (between 1 and 1000).
1376
+
1377
+ ## Example Usage
1378
+ Request the first 5 active alerts:
1379
+ \`\`\`json
1380
+ {
1381
+ "limit": 5
1382
+ }
1383
+ \`\`\``,
1384
+ "list-rule-evaluations.md": `# List Rule Evaluations Tool
1385
+
1386
+ List the evaluation history for a specific rule. This tool shows when a rule was evaluated and the results of each evaluation.
1387
+
1388
+ ## Parameters
1389
+ - \`ruleId\` (required): The ID of the rule to get evaluations for
1390
+ - \`beginTimestamp\` (optional): Start time for the evaluation period (Unix timestamp)
1391
+ - \`endTimestamp\` (optional): End time for the evaluation period (Unix timestamp)
1392
+ - \`limit\` (optional): Maximum number of evaluations to return (1-1000)
1393
+ - \`tag\` (optional): Filter evaluations by tag
1394
+
1395
+ ## Example Usage
1396
+ Get recent evaluations for a rule:
1397
+ \`\`\`json
1398
+ {
1399
+ "ruleId": "rule-123",
1400
+ "limit": 10
1401
+ }
1402
+ \`\`\``,
1403
+ "list-rules.md": `# List Rules Tool
1404
+
1405
+ List rules in your JupiterOne account using cursor pagination. This tool returns a page of rule instances, including their IDs, names, descriptions, versions, polling intervals, and other metadata. Use the cursor parameter to navigate through pages of results. This does not get alerts, but rather the configuration behind what may generate an alert, or other workflow action.
1406
+
1407
+ ## Parameters
1408
+ - \`limit\` (optional): Maximum number of rules to return per page (between 1 and 1000). Defaults to 100 if not specified.
1409
+ - \`cursor\` (optional): Pagination cursor to get the next page of results. Use the \`endCursor\` from a previous response's \`pageInfo\`. Omit this parameter to get the first page.
1410
+
1411
+ ## Example Usage
1412
+ Get the first page of rules (default page size):
1413
+ \`\`\`json
1414
+ {}
1415
+ \`\`\`
1416
+
1417
+ Get the first page with specific limit:
1418
+ \`\`\`json
1419
+ {
1420
+ "limit": 50
1421
+ }
1422
+ \`\`\`
1423
+
1424
+ Get the next page using a cursor:
1425
+ \`\`\`json
1426
+ {
1427
+ "limit": 50,
1428
+ "cursor": "cursor_value_from_previous_response"
1429
+ }
1430
+ \`\`\`
1431
+
1432
+ ## Response Format
1433
+ All responses include pagination information:
1434
+ \`\`\`json
1435
+ {
1436
+ "returned": 50,
1437
+ "rules": [...],
1438
+ "pageInfo": {
1439
+ "hasNextPage": true,
1440
+ "endCursor": "cursor_for_next_page"
1441
+ }
1442
+ }
1443
+ \`\`\`
1444
+
1445
+ - \`returned\`: Number of rules in this page
1446
+ - \`rules\`: Array of rule objects
1447
+ - \`pageInfo.hasNextPage\`: Whether there are more pages available
1448
+ - \`pageInfo.endCursor\`: Cursor to use for the next page (if \`hasNextPage\` is true)
1449
+
1450
+ ## Pagination Pattern
1451
+ To get all rules across multiple pages:
1452
+ 1. Call with no cursor to get the first page
1453
+ 2. Check if \`pageInfo.hasNextPage\` is true
1454
+ 3. If true, call again with \`cursor\` set to \`pageInfo.endCursor\`
1455
+ 4. Repeat until \`hasNextPage\` is false`,
1456
+ "test-connection.md": `# Test Connection Tool
1457
+
1458
+ Test the connection to JupiterOne API and verify authentication credentials. This tool validates that the MCP server can successfully communicate with JupiterOne.
1459
+
1460
+ ## Parameters
1461
+ None required.
1462
+
1463
+ ## Example Usage
1464
+ Test the connection:
1465
+ \`\`\`json
1466
+ {}
1467
+ \`\`\``,
1468
+ "update-dashboard.md": `Patch an existing dashboard's layout configuration. This tool is primarily used for modifying the layout of widgets on a dashboard after they have been created.
1469
+ You will always want to call this after creating a dashboard and all its widgets so you can give a favorable layout to the user. Widgets should always have a size specified.
1470
+ The layout configuration is organized by screen breakpoint sizes (xs, sm, md, lg, xl) and includes positioning information for each widget. Each layout item contains:
1471
+
1472
+ - \`i\`: Widget ID
1473
+ - \`x\`: X coordinate (horizontal position)
1474
+ - \`y\`: Y coordinate (vertical position)
1475
+ - \`w\`: Width in grid units
1476
+ - \`h\`: Height in grid units
1477
+ - \`moved\`: Whether the widget has been moved (should always be false)
1478
+ - \`static\`: Whether the widget position is fixed (should always be false)
1479
+
1480
+ Example layout configuration:
1481
+
1482
+ \`\`\`json
1483
+ {
1484
+ "xs": [],
1485
+ "sm": [],
1486
+ "md": [
1487
+ {
1488
+ "w": 5,
1489
+ "h": 2,
1490
+ "x": 0,
1491
+ "y": 0,
1492
+ "i": "widget-id-1",
1493
+ "moved": false,
1494
+ "static": false
1495
+ }
1496
+ ],
1497
+ "lg": [],
1498
+ "xl": []
1499
+ }
1500
+ \`\`\`
1501
+
1502
+ Here's an example layout that should be used for inspiration:
1503
+
1504
+ \`\`\`json
1505
+ "layouts": {
1506
+ "xs": [],
1507
+ "sm": [
1508
+ {
1509
+ "w": 1,
1510
+ "h": 1,
1511
+ "x": 0,
1512
+ "y": 0,
1513
+ "i": "cc1bb92b-736b-4b76-bb2a-4ffb3fb6db04"
1514
+ },
1515
+ {
1516
+ "w": 1,
1517
+ "h": 1,
1518
+ "x": 0,
1519
+ "y": 1,
1520
+ "i": "750ea929-fb31-46ef-b1d4-68c53b06e5a3"
1521
+ },
1522
+ {
1523
+ "w": 1,
1524
+ "h": 1,
1525
+ "x": 0,
1526
+ "y": 2,
1527
+ "i": "92507e3e-2c99-4089-b75a-ce97ad4743d5"
1528
+ },
1529
+ {
1530
+ "w": 2,
1531
+ "h": 2,
1532
+ "x": 0,
1533
+ "y": 3,
1534
+ "i": "f1535f10-a7ba-4c74-8ae6-d5be8c5655ee"
1535
+ },
1536
+ {
1537
+ "w": 1,
1538
+ "h": 1,
1539
+ "x": 0,
1540
+ "y": 7,
1541
+ "i": "29df3495-eea3-45a2-b779-788d92c8baa4"
1542
+ },
1543
+ {
1544
+ "w": 1,
1545
+ "h": 1,
1546
+ "x": 0,
1547
+ "y": 8,
1548
+ "i": "814000f8-9ffd-4ac3-90f8-26d321e9eba6"
1549
+ },
1550
+ {
1551
+ "w": 1,
1552
+ "h": 1,
1553
+ "x": 0,
1554
+ "y": 9,
1555
+ "i": "293fc7fd-eb34-4383-82b8-068b62ffdd61"
1556
+ },
1557
+ {
1558
+ "w": 1,
1559
+ "h": 1,
1560
+ "x": 0,
1561
+ "y": 10,
1562
+ "i": "b2e1c9b2-9da8-40d9-a068-9a6a4e0f2ed3"
1563
+ },
1564
+ {
1565
+ "w": 1,
1566
+ "h": 1,
1567
+ "x": 0,
1568
+ "y": 11,
1569
+ "i": "24bf65f6-e196-4e49-9e91-7d5bceb5c080"
1570
+ },
1571
+ {
1572
+ "w": 1,
1573
+ "h": 1,
1574
+ "x": 0,
1575
+ "y": 12,
1576
+ "i": "ce89d0fe-cd1d-4590-bffe-91c6f394ae4d"
1577
+ },
1578
+ {
1579
+ "w": 1,
1580
+ "h": 1,
1581
+ "x": 0,
1582
+ "y": 13,
1583
+ "i": "883dc4ba-6e75-44e6-8c42-8979c63c2a12"
1584
+ },
1585
+ {
1586
+ "w": 1,
1587
+ "h": 1,
1588
+ "x": 0,
1589
+ "y": 14,
1590
+ "i": "6ed5488a-0969-4cda-af4b-2ecb74b3963c"
1591
+ },
1592
+ {
1593
+ "w": 1,
1594
+ "h": 1,
1595
+ "x": 0,
1596
+ "y": 15,
1597
+ "i": "7a5c6998-df18-474c-be1c-5938a5e68943"
1598
+ },
1599
+ {
1600
+ "w": 1,
1601
+ "h": 1,
1602
+ "x": 0,
1603
+ "y": 16,
1604
+ "i": "3810193b-b6b6-428c-ab5c-48217d234ab4"
1605
+ },
1606
+ {
1607
+ "w": 1,
1608
+ "h": 1,
1609
+ "x": 0,
1610
+ "y": 17,
1611
+ "i": "f6a487a4-b385-421e-bfb8-03b1e651ce25"
1612
+ },
1613
+ {
1614
+ "w": 1,
1615
+ "h": 1,
1616
+ "x": 0,
1617
+ "y": 18,
1618
+ "i": "fd572af2-0df0-4d66-95e0-913cd79b973d"
1619
+ },
1620
+ {
1621
+ "w": 1,
1622
+ "h": 1,
1623
+ "x": 0,
1624
+ "y": 19,
1625
+ "i": "d1096b70-22fb-47d2-95d3-e1d63416d8e3"
1626
+ },
1627
+ {
1628
+ "w": 1,
1629
+ "h": 1,
1630
+ "x": 0,
1631
+ "y": 20,
1632
+ "i": "7d2e98b1-48cb-40bd-bef0-19e735c1fd3f"
1633
+ },
1634
+ {
1635
+ "w": 1,
1636
+ "h": 1,
1637
+ "x": 0,
1638
+ "y": 21,
1639
+ "i": "373a6c3e-77ee-4044-ba11-af176c813fb0"
1640
+ },
1641
+ {
1642
+ "w": 1,
1643
+ "h": 1,
1644
+ "x": 0,
1645
+ "y": 22,
1646
+ "i": "d679fc5e-ead3-4b7d-b650-559167edbeff"
1647
+ },
1648
+ {
1649
+ "w": 1,
1650
+ "h": 1,
1651
+ "x": 0,
1652
+ "y": 23,
1653
+ "i": "ce48c3e2-5ff9-42c6-85c3-e87ae9148762"
1654
+ },
1655
+ {
1656
+ "w": 1,
1657
+ "h": 1,
1658
+ "x": 0,
1659
+ "y": 24,
1660
+ "i": "384f066c-a4fe-4c26-b7cb-08f333cf9fac"
1661
+ },
1662
+ {
1663
+ "w": 1,
1664
+ "h": 1,
1665
+ "x": 0,
1666
+ "y": 25,
1667
+ "i": "b1caf3ba-4c6e-45aa-8def-e94f1d9e0e3c"
1668
+ },
1669
+ {
1670
+ "w": 1,
1671
+ "h": 1,
1672
+ "x": 0,
1673
+ "y": 26,
1674
+ "i": "c18dbb26-ecd1-4f19-ab9a-0de6980da2dc"
1675
+ },
1676
+ {
1677
+ "w": 1,
1678
+ "h": 1,
1679
+ "x": 0,
1680
+ "y": 27,
1681
+ "i": "450cc2ff-8f00-4311-b508-db8084df8725"
1682
+ },
1683
+ {
1684
+ "w": 2,
1685
+ "h": 2,
1686
+ "x": 0,
1687
+ "y": 5,
1688
+ "i": "befe345c-e392-40de-ad1b-97a38ac18503"
1689
+ },
1690
+ {
1691
+ "w": 1,
1692
+ "h": 1,
1693
+ "x": 0,
1694
+ "y": 28,
1695
+ "i": "e8f652ba-d3ac-4adb-a16e-f410af56414b"
1696
+ },
1697
+ {
1698
+ "w": 1,
1699
+ "h": 1,
1700
+ "x": 0,
1701
+ "y": 29,
1702
+ "i": "448f356d-d79f-47a2-a6ed-6ddf93d50f90"
1703
+ },
1704
+ {
1705
+ "w": 1,
1706
+ "h": 1,
1707
+ "x": 0,
1708
+ "y": 30,
1709
+ "i": "4d8ec87c-9a01-41eb-a659-bb9ad2afd283"
1710
+ },
1711
+ {
1712
+ "w": 1,
1713
+ "h": 1,
1714
+ "x": 0,
1715
+ "y": 31,
1716
+ "i": "6022a63e-38c0-42a4-bb9c-6a2c2e571da2"
1717
+ }
1718
+ ],
1719
+ "md": [],
1720
+ "lg": [
1721
+ {
1722
+ "w": 8,
1723
+ "h": 2,
1724
+ "x": 4,
1725
+ "y": 34,
1726
+ "i": "cc1bb92b-736b-4b76-bb2a-4ffb3fb6db04"
1727
+ },
1728
+ {
1729
+ "w": 12,
1730
+ "h": 2,
1731
+ "x": 0,
1732
+ "y": 9,
1733
+ "i": "750ea929-fb31-46ef-b1d4-68c53b06e5a3"
1734
+ },
1735
+ {
1736
+ "w": 12,
1737
+ "h": 1,
1738
+ "x": 0,
1739
+ "y": 8,
1740
+ "i": "92507e3e-2c99-4089-b75a-ce97ad4743d5"
1741
+ },
1742
+ {
1743
+ "w": 6,
1744
+ "h": 2,
1745
+ "x": 0,
1746
+ "y": 1,
1747
+ "i": "f1535f10-a7ba-4c74-8ae6-d5be8c5655ee"
1748
+ },
1749
+ {
1750
+ "w": 12,
1751
+ "h": 2,
1752
+ "x": 0,
1753
+ "y": 24,
1754
+ "i": "29df3495-eea3-45a2-b779-788d92c8baa4"
1755
+ },
1756
+ {
1757
+ "w": 12,
1758
+ "h": 2,
1759
+ "x": 0,
1760
+ "y": 29,
1761
+ "i": "814000f8-9ffd-4ac3-90f8-26d321e9eba6"
1762
+ },
1763
+ {
1764
+ "w": 4,
1765
+ "h": 2,
1766
+ "x": 0,
1767
+ "y": 18,
1768
+ "i": "293fc7fd-eb34-4383-82b8-068b62ffdd61"
1769
+ },
1770
+ {
1771
+ "w": 6,
1772
+ "h": 2,
1773
+ "x": 6,
1774
+ "y": 22,
1775
+ "i": "b2e1c9b2-9da8-40d9-a068-9a6a4e0f2ed3"
1776
+ },
1777
+ {
1778
+ "w": 12,
1779
+ "h": 2,
1780
+ "x": 0,
1781
+ "y": 15,
1782
+ "i": "24bf65f6-e196-4e49-9e91-7d5bceb5c080"
1783
+ },
1784
+ {
1785
+ "w": 12,
1786
+ "h": 1,
1787
+ "x": 0,
1788
+ "y": 33,
1789
+ "i": "ce89d0fe-cd1d-4590-bffe-91c6f394ae4d"
1790
+ },
1791
+ {
1792
+ "w": 6,
1793
+ "h": 2,
1794
+ "x": 6,
1795
+ "y": 20,
1796
+ "i": "883dc4ba-6e75-44e6-8c42-8979c63c2a12"
1797
+ },
1798
+ {
1799
+ "w": 6,
1800
+ "h": 2,
1801
+ "x": 0,
1802
+ "y": 22,
1803
+ "i": "6ed5488a-0969-4cda-af4b-2ecb74b3963c"
1804
+ },
1805
+ {
1806
+ "w": 6,
1807
+ "h": 2,
1808
+ "x": 6,
1809
+ "y": 31,
1810
+ "i": "7a5c6998-df18-474c-be1c-5938a5e68943"
1811
+ },
1812
+ {
1813
+ "w": 6,
1814
+ "h": 2,
1815
+ "x": 0,
1816
+ "y": 20,
1817
+ "i": "3810193b-b6b6-428c-ab5c-48217d234ab4"
1818
+ },
1819
+ {
1820
+ "w": 12,
1821
+ "h": 2,
1822
+ "x": 0,
1823
+ "y": 6,
1824
+ "i": "f6a487a4-b385-421e-bfb8-03b1e651ce25"
1825
+ },
1826
+ {
1827
+ "w": 6,
1828
+ "h": 2,
1829
+ "x": 6,
1830
+ "y": 3,
1831
+ "i": "fd572af2-0df0-4d66-95e0-913cd79b973d"
1832
+ },
1833
+ {
1834
+ "w": 7,
1835
+ "h": 2,
1836
+ "x": 5,
1837
+ "y": 11,
1838
+ "i": "d1096b70-22fb-47d2-95d3-e1d63416d8e3"
1839
+ },
1840
+ {
1841
+ "w": 12,
1842
+ "h": 1,
1843
+ "x": 0,
1844
+ "y": 5,
1845
+ "i": "7d2e98b1-48cb-40bd-bef0-19e735c1fd3f"
1846
+ },
1847
+ {
1848
+ "w": 6,
1849
+ "h": 2,
1850
+ "x": 0,
1851
+ "y": 3,
1852
+ "i": "373a6c3e-77ee-4044-ba11-af176c813fb0"
1853
+ },
1854
+ {
1855
+ "w": 8,
1856
+ "h": 2,
1857
+ "x": 4,
1858
+ "y": 18,
1859
+ "i": "d679fc5e-ead3-4b7d-b650-559167edbeff"
1860
+ },
1861
+ {
1862
+ "w": 6,
1863
+ "h": 2,
1864
+ "x": 0,
1865
+ "y": 31,
1866
+ "i": "ce48c3e2-5ff9-42c6-85c3-e87ae9148762"
1867
+ },
1868
+ {
1869
+ "w": 12,
1870
+ "h": 1,
1871
+ "x": 0,
1872
+ "y": 26,
1873
+ "i": "384f066c-a4fe-4c26-b7cb-08f333cf9fac"
1874
+ },
1875
+ {
1876
+ "w": 12,
1877
+ "h": 2,
1878
+ "x": 0,
1879
+ "y": 36,
1880
+ "i": "b1caf3ba-4c6e-45aa-8def-e94f1d9e0e3c"
1881
+ },
1882
+ {
1883
+ "w": 6,
1884
+ "h": 2,
1885
+ "x": 6,
1886
+ "y": 1,
1887
+ "i": "c18dbb26-ecd1-4f19-ab9a-0de6980da2dc"
1888
+ },
1889
+ {
1890
+ "w": 12,
1891
+ "h": 1,
1892
+ "x": 0,
1893
+ "y": 0,
1894
+ "i": "450cc2ff-8f00-4311-b508-db8084df8725"
1895
+ },
1896
+ {
1897
+ "w": 5,
1898
+ "h": 2,
1899
+ "x": 0,
1900
+ "y": 11,
1901
+ "i": "befe345c-e392-40de-ad1b-97a38ac18503"
1902
+ },
1903
+ {
1904
+ "w": 12,
1905
+ "h": 1,
1906
+ "x": 0,
1907
+ "y": 17,
1908
+ "i": "e8f652ba-d3ac-4adb-a16e-f410af56414b"
1909
+ },
1910
+ {
1911
+ "w": 12,
1912
+ "h": 2,
1913
+ "x": 0,
1914
+ "y": 13,
1915
+ "i": "448f356d-d79f-47a2-a6ed-6ddf93d50f90"
1916
+ },
1917
+ {
1918
+ "w": 4,
1919
+ "h": 2,
1920
+ "x": 0,
1921
+ "y": 34,
1922
+ "i": "4d8ec87c-9a01-41eb-a659-bb9ad2afd283"
1923
+ },
1924
+ {
1925
+ "w": 12,
1926
+ "h": 2,
1927
+ "x": 0,
1928
+ "y": 27,
1929
+ "i": "6022a63e-38c0-42a4-bb9c-6a2c2e571da2"
1930
+ }
1931
+ ],
1932
+ "xl": []
1933
+ }
1934
+ \`\`\`
1935
+ `,
1936
+ "update-inline-question-rule.md": `# JupiterOne Rule Update Tool - Complete Guide
1937
+
1938
+ **Purpose**: Updates existing inline question-based alert rules in JupiterOne. This tool modifies the configuration of an existing rule while preserving its identity and version history.
1939
+
1940
+ **Important**: Before updating a rule, use the \`get-rule-details\` tool to retrieve the current configuration. This ensures you have all required fields and can see what needs to be changed.
1941
+
1942
+ ## Key Requirements for Updates
1943
+
1944
+ ### 1. Required Fields for Updates
1945
+ When updating a rule, you must provide **ALL** fields, not just the ones you want to change. The update operation replaces the entire rule configuration, so missing fields will result in errors.
1946
+
1947
+ **Critical Required Fields**:
1948
+ - \`id\`: The existing rule ID (from \`get-rule-details\`)
1949
+ - \`version\`: The current version number (from \`get-rule-details\`)
1950
+ - \`specVersion\`: Usually 1
1951
+ - \`ignorePreviousResults\`: Must be included
1952
+ - \`templates\`: Must be included (use \`{}\` if empty)
1953
+ - \`tags\`: Must be included but should always be empty \`[]\` (deprecated)
1954
+ - \`labels\`: Use this for actual tagging functionality
1955
+ - \`resourceGroupId\`: Must be included (can be null)
1956
+ - \`remediationSteps\`: Must be included (can be null)
1957
+
1958
+ ### 2. Condition Format (Critical)
1959
+ The \`condition\` parameter must use JupiterOne's specific array format:
1960
+ - **Structure**: \`["LOGICAL_OPERATOR", [left_value, operator, right_value]]\`
1961
+ - **Example**: \`["AND", ["queries.queryName.total", ">", 0]]\`
1962
+ - **Supported operators**: \`>\`, \`<\`, \`>=\`, \`<=\`, \`=\`, \`!=\`
1963
+ - **Logical operators**: \`"AND"\`, \`"OR"\`
1964
+
1965
+ ### 3. Operations Structure
1966
+ The \`when\` clause should only contain:
1967
+ - \`type\`: Always \`"FILTER"\`
1968
+ - \`condition\`: The array format described above
1969
+ - **Do NOT include**: \`version\`, \`specVersion\` (these belong at the rule level, not in the when clause)
1970
+
1971
+ ### 4. Query Naming Convention
1972
+ - Query names in the \`queries\` array must match the references in conditions
1973
+ - Example: If query name is \`"users"\`, reference it as \`"queries.users.total"\`
1974
+ - **IMPORTANT**: Use \`"query0"\` as the standard query name for compatibility with existing patterns
1975
+
1976
+ ### 5. Version Management
1977
+ - The \`version\` field will be automatically incremented by JupiterOne
1978
+ - You must provide the current version number in your update request
1979
+ - Get the current version using \`get-rule-details\` before updating
1980
+
1981
+ ### 6. Tags vs Labels (Important)
1982
+ - **DEPRECATED**: The \`tags\` array field is deprecated and should always be set to an empty array \`[]\`
1983
+ - **USE INSTEAD**: For tagging functionality, use the \`labels\` field with key-value pairs
1984
+ - **Format**: \`labels: [{"labelName": "key", "labelValue": "value"}]\`
1985
+ - **When users ask for tagging**: Always use the \`labels\` field to meet their needs
1986
+ - **Note**: The \`tags\` field is still required in the schema for compatibility but should remain empty
1987
+
1988
+ ## Update Workflow
1989
+
1990
+ ### Step 1: Get Current Rule Configuration
1991
+ \`\`\`
1992
+ Use get-rule-details with the rule ID to get the current configuration
1993
+ \`\`\`
1994
+
1995
+ ### Step 2: Modify Required Fields
1996
+ Update only the fields you need to change while preserving all other required fields.
1997
+
1998
+ ### Step 3: Submit Update
1999
+ Use this tool with the complete configuration including your changes.
2000
+
2001
+ ## Required Schema Fields for Updates
2002
+
2003
+ ### Complete Required Parameters for update-inline-question-rule
2004
+ **CRITICAL**: All of these fields must be included for successful rule updates:
2005
+
2006
+ \`\`\`json
2007
+ {
2008
+ "id": "existing-rule-id",
2009
+ "name": "Updated Rule Name",
2010
+ "description": "Updated rule description",
2011
+ "notifyOnFailure": true,
2012
+ "triggerActionsOnNewEntitiesOnly": true,
2013
+ "ignorePreviousResults": false,
2014
+ "pollingInterval": "ONE_DAY",
2015
+ "specVersion": 1,
2016
+ "version": 2,
2017
+ "templates": {},
2018
+ "outputs": ["alertLevel"],
2019
+ "tags": [],
2020
+ "labels": [
2021
+ {"labelName": "environment", "labelValue": "production"},
2022
+ {"labelName": "team", "labelValue": "security"}
2023
+ ],
2024
+ "resourceGroupId": null,
2025
+ "remediationSteps": null,
2026
+ "question": {
2027
+ "queries": [
2028
+ {
2029
+ "query": "FIND Entity...",
2030
+ "name": "query0",
2031
+ "version": "v1",
2032
+ "includeDeleted": false
2033
+ }
2034
+ ]
2035
+ },
2036
+ "operations": [
2037
+ {
2038
+ "when": {
2039
+ "type": "FILTER",
2040
+ "condition": ["AND", ["queries.query0.total", ">", 0]]
2041
+ },
2042
+ "actions": [...]
2043
+ }
2044
+ ]
2045
+ }
2046
+ \`\`\`
2047
+
2048
+ **Key Update Requirements**:
2049
+ - \`id\`: Must match the existing rule ID
2050
+ - \`version\`: Must be the current version number from the existing rule
2051
+ - \`ignorePreviousResults\`: Must be included (typically \`false\`)
2052
+ - \`templates\`: Must be included (use \`{}\` if empty)
2053
+ - \`tags\`: Must be included but should always be empty \`[]\` (deprecated field)
2054
+ - \`labels\`: Use this for actual tagging functionality with key-value pairs
2055
+ - \`resourceGroupId\`: Must be included (can be null)
2056
+ - \`remediationSteps\`: Must be included (can be null)
2057
+ - Query \`name\`: Use \`"query0"\` for primary query
2058
+ - Query \`version\`: Include \`"v1"\` for compatibility
2059
+ - Query \`includeDeleted\`: Must be explicitly set to \`false\`
2060
+
2061
+ ## Available Action Types
2062
+
2063
+ ### 1. SET_PROPERTY
2064
+ Sets a property value on the alert (commonly used for alert severity levels).
2065
+
2066
+ **Configuration**:
2067
+ \`\`\`json
2068
+ {
2069
+ "type": "SET_PROPERTY",
2070
+ "targetProperty": "alertLevel",
2071
+ "targetValue": "CRITICAL"
2072
+ }
2073
+ \`\`\`
2074
+
2075
+ **Common Values for alertLevel**: \`"LOW"\`, \`"MEDIUM"\`, \`"HIGH"\`, \`"CRITICAL"\`, \`"INFO"\`
2076
+
2077
+ ### 2. CREATE_ALERT
2078
+ Creates a basic alert in JupiterOne.
2079
+
2080
+ **Configuration**:
2081
+ \`\`\`json
2082
+ {
2083
+ "type": "CREATE_ALERT"
2084
+ }
2085
+ \`\`\`
2086
+
2087
+ **Note**: This is the most basic action and should almost always be included.
2088
+
2089
+ ### 3. SEND_EMAIL
2090
+ Sends email notifications to specified recipients.
2091
+
2092
+ **Configuration**:
2093
+ \`\`\`json
2094
+ {
2095
+ "type": "SEND_EMAIL",
2096
+ "recipients": ["user1@company.com", "user2@company.com"],
2097
+ "body": "Affected Items: <br><br>* {{queries.query0.data|mapProperty('displayName')|join('<br>* ')}}"
2098
+ }
2099
+ \`\`\`
2100
+
2101
+ ### 4. TAG_ENTITIES
2102
+ Adds or removes tags from entities that triggered the rule.
2103
+
2104
+ **Configuration**:
2105
+ \`\`\`json
2106
+ {
2107
+ "type": "TAG_ENTITIES",
2108
+ "entities": "{{queries.query0.data}}",
2109
+ "tags": [
2110
+ {"name": "existing tag to remove", "value": null},
2111
+ {"name": "new tag", "value": "tag value"}
2112
+ ]
2113
+ }
2114
+ \`\`\`
2115
+
2116
+ ### 5. SEND_SLACK_MESSAGE
2117
+ Sends messages to Slack channels (requires Slack integration).
2118
+
2119
+ **Configuration**:
2120
+ \`\`\`json
2121
+ {
2122
+ "integrationInstanceId": "d97d9127-c532-410a-bf0a-9ea93f66c3d2",
2123
+ "type": "SEND_SLACK_MESSAGE",
2124
+ "channels": ["#security-alerts", "#general"],
2125
+ "body": "*Affected Items:* \n\n- {{queries.query0.data|mapProperty('displayName')|join('\n- ')}}"
2126
+ }
2127
+ \`\`\`
2128
+
2129
+ ### 6. SEND_TO_S3
2130
+ Sends alert data to an S3 bucket (requires AWS S3 integration).
2131
+
2132
+ **Configuration**:
2133
+ \`\`\`json
2134
+ {
2135
+ "integrationInstanceId": "f89568b4-2a1b-4bd8-8abd-aee21270df75",
2136
+ "type": "SEND_TO_S3",
2137
+ "bucket": "security-alerts-bucket",
2138
+ "region": "us-east-1",
2139
+ "data": {
2140
+ "description": "{{alertWebLink}}\n\n**Affected Items:**\n\n* {{queries.query0.data|mapProperty('displayName')|join('\n* ')}}"
2141
+ }
2142
+ }
2143
+ \`\`\`
2144
+
2145
+ ### 7. CREATE_JIRA_TICKET
2146
+ Creates a Jira ticket for the alert (requires Jira integration).
2147
+
2148
+ **Configuration**:
2149
+ \`\`\`json
2150
+ {
2151
+ "integrationInstanceId": "53a99eaa-18a5-45ef-b748-2de39d642a91",
2152
+ "type": "CREATE_JIRA_TICKET",
2153
+ "entityClass": "Finding",
2154
+ "summary": "Security Alert: Critical Unencrypted Data Found",
2155
+ "issueType": "Bug",
2156
+ "project": "SEC",
2157
+ "updateContentOnChanges": false,
2158
+ "additionalFields": {
2159
+ "description": {
2160
+ "type": "doc",
2161
+ "version": 1,
2162
+ "content": [
2163
+ {
2164
+ "type": "paragraph",
2165
+ "content": [
2166
+ {
2167
+ "type": "text",
2168
+ "text": "{{alertWebLink}}\n\n**Affected Items:**\n\n* {{queries.query0.data|mapProperty('displayName')|join('\n* ')}}"
2169
+ }
2170
+ ]
2171
+ }
2172
+ ]
2173
+ }
2174
+ }
2175
+ }
2176
+ \`\`\`
2177
+
2178
+ ## Template Variables and Formatting
2179
+
2180
+ ### Available Variables
2181
+ - \`{{alertWebLink}}\` - Direct link to the alert in JupiterOne
2182
+ - \`{{queries.queryName.data}}\` - Array of entities from the specified query
2183
+ - \`{{queries.queryName.total}}\` - Count of entities from the query
2184
+
2185
+ ### Data Formatting
2186
+ - \`|mapProperty('fieldName')\` - Extract specific field from each entity
2187
+ - \`|join('separator')\` - Join array elements with specified separator
2188
+ - Example: \`{{queries.users.data|mapProperty('displayName')|join(', ')}}\` - Creates comma-separated list of user names
2189
+
2190
+ ## Integration Dependencies
2191
+
2192
+ For actions requiring integrations, you may need to:
2193
+ 1. Query available integration instances using \`get-integration-instances\`
2194
+ 2. Ask the user which integration to use
2195
+ 3. Use the integration's \`id\` as the \`integrationInstanceId\`
2196
+
2197
+ **Actions requiring integrations**:
2198
+ - \`SEND_SLACK_MESSAGE\` (Slack integration)
2199
+ - \`SEND_TO_S3\` (AWS S3 integration)
2200
+ - \`CREATE_JIRA_TICKET\` (Jira integration)
2201
+
2202
+ ## Working Example Update
2203
+
2204
+ ### Complete Working Rule Update Structure
2205
+ \`\`\`json
2206
+ {
2207
+ "id": "12345678-1234-1234-1234-123456789abc",
2208
+ "name": "Updated Rule Name",
2209
+ "description": "Updated rule description",
2210
+ "notifyOnFailure": true,
2211
+ "triggerActionsOnNewEntitiesOnly": true,
2212
+ "ignorePreviousResults": false,
2213
+ "pollingInterval": "ONE_DAY",
2214
+ "specVersion": 1,
2215
+ "version": 3,
2216
+ "templates": {},
2217
+ "outputs": ["alertLevel"],
2218
+ "tags": [],
2219
+ "labels": [
2220
+ {"labelName": "severity", "labelValue": "high"},
2221
+ {"labelName": "category", "labelValue": "security"}
2222
+ ],
2223
+ "resourceGroupId": null,
2224
+ "remediationSteps": "1. Review the affected entities\n2. Apply security patches\n3. Update configurations",
2225
+ "question": {
2226
+ "queries": [
2227
+ {
2228
+ "query": "FIND Entity WITH condition",
2229
+ "name": "query0",
2230
+ "version": "v1",
2231
+ "includeDeleted": false
2232
+ }
2233
+ ]
2234
+ },
2235
+ "operations": [
2236
+ {
2237
+ "when": {
2238
+ "type": "FILTER",
2239
+ "condition": ["AND", ["queries.query0.total", ">", 0]]
2240
+ },
2241
+ "actions": [
2242
+ {
2243
+ "type": "SET_PROPERTY",
2244
+ "targetProperty": "alertLevel",
2245
+ "targetValue": "CRITICAL"
2246
+ },
2247
+ {
2248
+ "type": "CREATE_ALERT"
2249
+ },
2250
+ {
2251
+ "type": "SEND_EMAIL",
2252
+ "recipients": ["updated-user@company.com"],
2253
+ "body": "Updated notification: {{alertWebLink}}"
2254
+ }
2255
+ ]
2256
+ }
2257
+ ]
2258
+ }
2259
+ \`\`\`
2260
+
2261
+ ## Common Update Scenarios
2262
+
2263
+ ### 1. Changing Notification Recipients
2264
+ Update only the \`recipients\` array in the \`SEND_EMAIL\` action while preserving all other fields.
2265
+
2266
+ ### 2. Modifying Polling Interval
2267
+ Update the \`pollingInterval\` field while keeping all other configuration the same.
2268
+
2269
+ ### 3. Adding New Actions
2270
+ Add new actions to the \`actions\` array in the operations.
2271
+
2272
+ ### 4. Updating Query Logic
2273
+ Modify the \`query\` string in the queries array or adjust the \`condition\` in operations.
2274
+
2275
+ ### 5. Changing Labels
2276
+ Update the \`labels\` array to add, remove, or modify rule labels.
2277
+
2278
+ ## Debugging Tips
2279
+ - Always start by getting the current rule configuration with \`get-rule-details\`
2280
+ - Ensure the \`version\` number matches the current rule version
2281
+ - Include ALL required fields, even if they're not changing
2282
+ - If you get "Invalid conjunction operator" errors, check the condition array format
2283
+ - If you get "additional properties" errors, remove extra fields from the \`when\` clause
2284
+ - If you get missing property errors, ensure all required schema fields are included
2285
+ - **Always include**: \`id\`, \`version\`, \`ignorePreviousResults\`, \`templates\`, \`tags\`, \`labels\`, \`resourceGroupId\`, \`remediationSteps\`
2286
+ - Use \`"query0"\` as the standard query name for compatibility
2287
+
2288
+ ## Best Practices for Updates
2289
+ - Always retrieve the current rule configuration first using \`get-rule-details\`
2290
+ - Only modify the fields that actually need to change
2291
+ - Preserve the existing \`version\` number (it will be auto-incremented)
2292
+ - Use the \`labels\` field for rule organization and tagging (not the deprecated \`tags\` field)
2293
+ - Test rule changes with simple modifications first
2294
+ - Document changes in the \`description\` field if significant
2295
+ - When users request tagging functionality, use the \`labels\` field with key-value pairs
2296
+ - Always include \`CREATE_ALERT\` action as a baseline unless specifically removing it
2297
+
2298
+ This format ensures reliable rule updates and helps avoid common pitfalls encountered during rule modification.`
2299
+ };
2300
+ //# sourceMappingURL=description-map.js.map