@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
@@ -1,289 +1,456 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { z } from 'zod';
4
- import { JupiterOneClient } from '../client/jupiterone-client.js';
5
- import { loadDescription } from '../utils/load-description.js';
6
- import { J1QLValidator } from '../utils/j1ql-validator.js';
7
- export class JupiterOneMcpServer {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JupiterOneMcpServer = void 0;
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const zod_1 = require("zod");
7
+ const jupiterone_client_js_1 = require("../client/jupiterone-client.js");
8
+ const load_description_js_1 = require("../utils/load-description.js");
9
+ const j1ql_validator_js_1 = require("../utils/j1ql-validator.js");
10
+ class JupiterOneMcpServer {
8
11
  server;
9
12
  client;
10
13
  validator;
14
+ hasEnvironmentAccount;
11
15
  constructor(config) {
12
- this.client = new JupiterOneClient(config);
13
- this.validator = new J1QLValidator(this.client.j1qlService);
14
- this.server = new McpServer({
16
+ this.client = new jupiterone_client_js_1.JupiterOneClient(config);
17
+ this.validator = new j1ql_validator_js_1.J1QLValidator(this.client.j1qlService);
18
+ this.server = new mcp_js_1.McpServer({
15
19
  name: 'jupiterone-mcp',
16
20
  version: '1.0.0',
17
21
  });
22
+ this.hasEnvironmentAccount = !config.accountId;
18
23
  this.setupTools();
19
24
  }
25
+ registerTool(options) {
26
+ const { name, schema, handler, description } = options;
27
+ let finalSchema = schema;
28
+ if (this.hasEnvironmentAccount) {
29
+ finalSchema = {
30
+ ...schema,
31
+ accountId: zod_1.z
32
+ .string()
33
+ .describe('JupiterOne Account ID for this request. This should be explicitly asked for with the first tool call.'),
34
+ };
35
+ }
36
+ this.server.tool(name, description || '', finalSchema, async (params) => {
37
+ let client = this.client;
38
+ let toolParams = params;
39
+ let validator = this.validator;
40
+ if (this.hasEnvironmentAccount) {
41
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
+ const { accountId, ...otherParams } = params;
43
+ if (!accountId) {
44
+ return {
45
+ content: [
46
+ {
47
+ type: 'text',
48
+ text: 'Error: accountId is required for this operation because no default JUPITERONE_ACCOUNT_ID is configured.',
49
+ },
50
+ ],
51
+ isError: true,
52
+ };
53
+ }
54
+ client = this.client.cloneWithAccountId(accountId);
55
+ validator = new j1ql_validator_js_1.J1QLValidator(client.j1qlService);
56
+ toolParams = otherParams;
57
+ }
58
+ return handler(toolParams, client, validator);
59
+ });
60
+ }
20
61
  setupTools() {
21
62
  // Tool: List all rules
22
- this.server.tool('list-rules', loadDescription('list-rules.md'), {
23
- limit: z.number().min(1).max(1000).optional(),
24
- cursor: z.string().optional(),
25
- }, async ({ limit, cursor }) => {
26
- try {
27
- const response = await this.client.listRuleInstances(limit, cursor);
28
- const instances = response.questionInstances || [];
29
- return {
30
- content: [
31
- {
32
- type: 'text',
33
- text: JSON.stringify({
34
- returned: instances.length,
35
- rules: instances.map((instance) => ({
36
- id: instance.id,
37
- name: instance.name,
38
- description: instance.description,
39
- version: instance.version,
40
- pollingInterval: instance.pollingInterval,
41
- lastEvaluationStartOn: instance.lastEvaluationStartOn,
42
- lastEvaluationEndOn: instance.lastEvaluationEndOn,
43
- latestAlertId: instance.latestAlertId,
44
- latestAlertIsActive: instance.latestAlertIsActive,
45
- type: instance.type,
46
- tags: instance.tags,
47
- outputs: instance.outputs,
48
- })),
49
- pageInfo: response.pageInfo,
50
- }, null, 2),
51
- },
52
- ],
53
- };
54
- }
55
- catch (error) {
56
- return {
57
- content: [
58
- {
59
- type: 'text',
60
- text: `Error listing rules: ${error instanceof Error ? error.message : 'Unknown error'}`,
61
- },
62
- ],
63
- isError: true,
64
- };
65
- }
63
+ this.registerTool({
64
+ name: 'list-rules',
65
+ description: (0, load_description_js_1.loadDescription)('list-rules.md'),
66
+ schema: {
67
+ limit: zod_1.z.number().min(1).max(1000).optional(),
68
+ cursor: zod_1.z.string().optional(),
69
+ },
70
+ handler: async ({ limit, cursor }, client) => {
71
+ try {
72
+ const response = await client.listRuleInstances(limit, cursor);
73
+ const instances = response.questionInstances || [];
74
+ return {
75
+ content: [
76
+ {
77
+ type: 'text',
78
+ text: JSON.stringify({
79
+ returned: instances.length,
80
+ rules: instances.map((instance) => ({
81
+ id: instance.id,
82
+ name: instance.name,
83
+ description: instance.description,
84
+ version: instance.version,
85
+ pollingInterval: instance.pollingInterval,
86
+ lastEvaluationStartOn: instance.lastEvaluationStartOn,
87
+ lastEvaluationEndOn: instance.lastEvaluationEndOn,
88
+ latestAlertId: instance.latestAlertId,
89
+ latestAlertIsActive: instance.latestAlertIsActive,
90
+ type: instance.type,
91
+ tags: instance.tags,
92
+ outputs: instance.outputs,
93
+ })),
94
+ pageInfo: response.pageInfo,
95
+ }, null, 2),
96
+ },
97
+ ],
98
+ };
99
+ }
100
+ catch (error) {
101
+ return {
102
+ content: [
103
+ {
104
+ type: 'text',
105
+ text: `Error listing rules: ${error instanceof Error ? error.message : 'Unknown error'}`,
106
+ },
107
+ ],
108
+ isError: true,
109
+ };
110
+ }
111
+ },
66
112
  });
67
113
  // Tool: Get rule details
68
- this.server.tool('get-rule-details', {
69
- ruleId: z.string(),
70
- }, async ({ ruleId }) => {
71
- try {
72
- const instances = await this.client.getAllRuleInstances();
73
- const rule = instances.find((instance) => instance.id === ruleId);
74
- if (!rule) {
114
+ this.registerTool({
115
+ name: 'get-rule-details',
116
+ description: (0, load_description_js_1.loadDescription)('get-rule-details.md'),
117
+ schema: {
118
+ ruleId: zod_1.z.string(),
119
+ },
120
+ handler: async ({ ruleId }, client) => {
121
+ try {
122
+ const instances = await client.getAllRuleInstances();
123
+ const rule = instances.find((instance) => instance.id === ruleId);
124
+ if (!rule) {
125
+ return {
126
+ content: [
127
+ {
128
+ type: 'text',
129
+ text: `Rule with ID ${ruleId} not found`,
130
+ },
131
+ ],
132
+ isError: true,
133
+ };
134
+ }
75
135
  return {
76
136
  content: [
77
137
  {
78
138
  type: 'text',
79
- text: `Rule with ID ${ruleId} not found`,
139
+ text: JSON.stringify({
140
+ id: rule.id,
141
+ resourceGroupId: rule.resourceGroupId,
142
+ accountId: rule.accountId,
143
+ name: rule.name,
144
+ description: rule.description,
145
+ version: rule.version,
146
+ lastEvaluationStartOn: rule.lastEvaluationStartOn,
147
+ lastEvaluationEndOn: rule.lastEvaluationEndOn,
148
+ evaluationStep: rule.evaluationStep,
149
+ specVersion: rule.specVersion,
150
+ notifyOnFailure: rule.notifyOnFailure,
151
+ triggerActionsOnNewEntitiesOnly: rule.triggerActionsOnNewEntitiesOnly,
152
+ ignorePreviousResults: rule.ignorePreviousResults,
153
+ pollingInterval: rule.pollingInterval,
154
+ templates: rule.templates,
155
+ outputs: rule.outputs,
156
+ labels: rule.labels?.map((label) => ({
157
+ labelName: label.labelName,
158
+ labelValue: label.labelValue,
159
+ })) || [],
160
+ question: rule.question
161
+ ? {
162
+ queries: rule.question.queries?.map((query) => ({
163
+ query: query.query,
164
+ name: query.name,
165
+ includeDeleted: query.includeDeleted,
166
+ })) || [],
167
+ }
168
+ : null,
169
+ questionId: rule.questionId,
170
+ latest: rule.latest,
171
+ deleted: rule.deleted,
172
+ type: rule.type,
173
+ operations: rule.operations?.map((op) => ({
174
+ when: op.when,
175
+ actions: op.actions,
176
+ })) || [],
177
+ latestAlertId: rule.latestAlertId,
178
+ latestAlertIsActive: rule.latestAlertIsActive,
179
+ state: rule.state
180
+ ? {
181
+ actions: rule.state.actions,
182
+ }
183
+ : null,
184
+ tags: rule.tags,
185
+ remediationSteps: rule.remediationSteps,
186
+ }, null, 2),
187
+ },
188
+ ],
189
+ };
190
+ }
191
+ catch (error) {
192
+ return {
193
+ content: [
194
+ {
195
+ type: 'text',
196
+ text: `Error getting rule details: ${error instanceof Error ? error.message : 'Unknown error'}`,
80
197
  },
81
198
  ],
82
199
  isError: true,
83
200
  };
84
201
  }
85
- return {
86
- content: [
87
- {
88
- type: 'text',
89
- text: JSON.stringify({
90
- id: rule.id,
91
- resourceGroupId: rule.resourceGroupId,
92
- accountId: rule.accountId,
93
- name: rule.name,
94
- description: rule.description,
95
- version: rule.version,
96
- lastEvaluationStartOn: rule.lastEvaluationStartOn,
97
- lastEvaluationEndOn: rule.lastEvaluationEndOn,
98
- evaluationStep: rule.evaluationStep,
99
- specVersion: rule.specVersion,
100
- notifyOnFailure: rule.notifyOnFailure,
101
- triggerActionsOnNewEntitiesOnly: rule.triggerActionsOnNewEntitiesOnly,
102
- ignorePreviousResults: rule.ignorePreviousResults,
103
- pollingInterval: rule.pollingInterval,
104
- templates: rule.templates,
105
- outputs: rule.outputs,
106
- labels: rule.labels?.map((label) => ({
107
- labelName: label.labelName,
108
- labelValue: label.labelValue,
109
- })) || [],
110
- question: rule.question
111
- ? {
112
- queries: rule.question.queries?.map((query) => ({
113
- query: query.query,
114
- name: query.name,
115
- includeDeleted: query.includeDeleted,
116
- })) || [],
117
- }
118
- : null,
119
- questionId: rule.questionId,
120
- latest: rule.latest,
121
- deleted: rule.deleted,
122
- type: rule.type,
123
- operations: rule.operations?.map((op) => ({
124
- when: op.when,
125
- actions: op.actions,
126
- })) || [],
127
- latestAlertId: rule.latestAlertId,
128
- latestAlertIsActive: rule.latestAlertIsActive,
129
- state: rule.state
130
- ? {
131
- actions: rule.state.actions,
132
- }
133
- : null,
134
- tags: rule.tags,
135
- remediationSteps: rule.remediationSteps,
136
- }, null, 2),
137
- },
138
- ],
139
- };
140
- }
141
- catch (error) {
142
- return {
143
- content: [
144
- {
145
- type: 'text',
146
- text: `Error getting rule details: ${error instanceof Error ? error.message : 'Unknown error'}`,
147
- },
148
- ],
149
- isError: true,
150
- };
151
- }
202
+ },
152
203
  });
153
204
  // Tool: Test connection
154
- this.server.tool('test-connection', {}, async () => {
155
- try {
156
- const isConnected = await this.client.testConnection();
157
- const accountInfo = isConnected ? await this.client.getAccountInfo() : null;
158
- return {
159
- content: [
160
- {
161
- type: 'text',
162
- text: JSON.stringify({
163
- connected: isConnected,
164
- account: accountInfo,
165
- }, null, 2),
166
- },
167
- ],
168
- };
169
- }
170
- catch (error) {
171
- return {
172
- content: [
173
- {
174
- type: 'text',
175
- text: `Connection test failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
176
- },
177
- ],
178
- isError: true,
179
- };
180
- }
205
+ this.registerTool({
206
+ name: 'test-connection',
207
+ description: (0, load_description_js_1.loadDescription)('test-connection.md'),
208
+ schema: {},
209
+ handler: async (_, client) => {
210
+ try {
211
+ const isConnected = await client.testConnection();
212
+ const accountInfo = isConnected ? await client.getAccountInfo() : null;
213
+ return {
214
+ content: [
215
+ {
216
+ type: 'text',
217
+ text: JSON.stringify({
218
+ connected: isConnected,
219
+ account: accountInfo,
220
+ }, null, 2),
221
+ },
222
+ ],
223
+ };
224
+ }
225
+ catch (error) {
226
+ return {
227
+ content: [
228
+ {
229
+ type: 'text',
230
+ text: `Connection test failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
231
+ },
232
+ ],
233
+ isError: true,
234
+ };
235
+ }
236
+ },
181
237
  });
182
238
  // Tool: Evaluate rule
183
- this.server.tool('evaluate-rule', {
184
- ruleId: z.string(),
185
- }, async ({ ruleId }) => {
186
- try {
187
- const result = await this.client.evaluateRuleInstance(ruleId);
188
- return {
189
- content: [
190
- {
191
- type: 'text',
192
- text: JSON.stringify({
193
- ruleId,
194
- id: result.id,
195
- __typename: result.__typename,
196
- }, null, 2),
197
- },
198
- ],
199
- };
200
- }
201
- catch (error) {
202
- return {
203
- content: [
204
- {
205
- type: 'text',
206
- text: `Error evaluating rule: ${error instanceof Error ? error.message : 'Unknown error'}`,
207
- },
208
- ],
209
- isError: true,
210
- };
211
- }
239
+ this.registerTool({
240
+ name: 'evaluate-rule',
241
+ description: (0, load_description_js_1.loadDescription)('evaluate-rule.md'),
242
+ schema: {
243
+ ruleId: zod_1.z.string(),
244
+ },
245
+ handler: async ({ ruleId }, client) => {
246
+ try {
247
+ const result = await client.evaluateRuleInstance(ruleId);
248
+ return {
249
+ content: [
250
+ {
251
+ type: 'text',
252
+ text: JSON.stringify({
253
+ ruleId,
254
+ id: result.id,
255
+ __typename: result.__typename,
256
+ }, null, 2),
257
+ },
258
+ ],
259
+ };
260
+ }
261
+ catch (error) {
262
+ return {
263
+ content: [
264
+ {
265
+ type: 'text',
266
+ text: `Error evaluating rule: ${error instanceof Error ? error.message : 'Unknown error'}`,
267
+ },
268
+ ],
269
+ isError: true,
270
+ };
271
+ }
272
+ },
212
273
  });
213
274
  // Tool: Get active alerts
214
- this.server.tool('get-active-alerts', loadDescription('list-alerts.md'), {
215
- limit: z.number().min(1).max(1000).optional(),
216
- }, async ({ limit }) => {
217
- try {
218
- const instances = await this.client.getAllAlertInstances('ACTIVE');
219
- if (!instances || !Array.isArray(instances)) {
220
- throw new Error('Invalid response from JupiterOne API: instances is not an array');
275
+ this.registerTool({
276
+ name: 'get-active-alerts',
277
+ description: (0, load_description_js_1.loadDescription)('list-alerts.md'),
278
+ schema: {
279
+ limit: zod_1.z.number().min(1).max(1000).optional(),
280
+ },
281
+ handler: async ({ limit }, client) => {
282
+ try {
283
+ const instances = await client.getAllAlertInstances('ACTIVE');
284
+ if (!instances || !Array.isArray(instances)) {
285
+ throw new Error('Invalid response from JupiterOne API: instances is not an array');
286
+ }
287
+ const limitedInstances = limit ? instances.slice(0, limit) : instances;
288
+ return {
289
+ content: [
290
+ {
291
+ type: 'text',
292
+ text: JSON.stringify({
293
+ total: instances.length,
294
+ returned: limitedInstances.length,
295
+ activeAlerts: limitedInstances.map((instance) => ({
296
+ id: instance.id,
297
+ name: instance.questionRuleInstance?.name ||
298
+ instance.reportRuleInstance?.name ||
299
+ 'Unknown',
300
+ description: instance.questionRuleInstance?.description ||
301
+ instance.reportRuleInstance?.description,
302
+ level: instance.level,
303
+ status: instance.status,
304
+ createdOn: instance.createdOn,
305
+ lastUpdatedOn: instance.lastUpdatedOn,
306
+ lastEvaluationBeginOn: instance.lastEvaluationBeginOn,
307
+ lastEvaluationEndOn: instance.lastEvaluationEndOn,
308
+ recordCount: instance.lastEvaluationResult?.rawDataDescriptors?.[0]?.recordCount || 0,
309
+ tags: instance.questionRuleInstance?.tags || [],
310
+ labels: instance.questionRuleInstance?.labels || [],
311
+ outputs: instance.lastEvaluationResult?.outputs || [],
312
+ users: instance.users,
313
+ ruleId: instance.ruleId,
314
+ ruleVersion: instance.ruleVersion,
315
+ endReason: instance.endReason,
316
+ dismissedOn: instance.dismissedOn,
317
+ })),
318
+ }, null, 2),
319
+ },
320
+ ],
321
+ };
221
322
  }
222
- const limitedInstances = limit ? instances.slice(0, limit) : instances;
223
- return {
224
- content: [
225
- {
226
- type: 'text',
227
- text: JSON.stringify({
228
- total: instances.length,
229
- returned: limitedInstances.length,
230
- activeAlerts: limitedInstances.map((instance) => ({
231
- id: instance.id,
232
- name: instance.questionRuleInstance?.name ||
233
- instance.reportRuleInstance?.name ||
234
- 'Unknown',
235
- description: instance.questionRuleInstance?.description ||
236
- instance.reportRuleInstance?.description,
237
- level: instance.level,
238
- status: instance.status,
239
- createdOn: instance.createdOn,
240
- lastUpdatedOn: instance.lastUpdatedOn,
241
- lastEvaluationBeginOn: instance.lastEvaluationBeginOn,
242
- lastEvaluationEndOn: instance.lastEvaluationEndOn,
243
- recordCount: instance.lastEvaluationResult?.rawDataDescriptors?.[0]?.recordCount || 0,
244
- tags: instance.questionRuleInstance?.tags || [],
245
- labels: instance.questionRuleInstance?.labels || [],
246
- outputs: instance.lastEvaluationResult?.outputs || [],
247
- users: instance.users,
248
- ruleId: instance.ruleId,
249
- ruleVersion: instance.ruleVersion,
250
- endReason: instance.endReason,
251
- dismissedOn: instance.dismissedOn,
252
- })),
253
- }, null, 2),
254
- },
255
- ],
256
- };
257
- }
258
- catch (error) {
259
- console.error('Error in get-active-alerts:', error);
260
- return {
261
- content: [
262
- {
263
- type: 'text',
264
- text: `Error getting active alerts: ${error instanceof Error ? error.message : 'Unknown error'}. Please check your JupiterOne API credentials and connection.`,
265
- },
266
- ],
267
- isError: true,
268
- };
269
- }
323
+ catch (error) {
324
+ console.error('Error in get-active-alerts:', error);
325
+ return {
326
+ content: [
327
+ {
328
+ type: 'text',
329
+ text: `Error getting active alerts: ${error instanceof Error ? error.message : 'Unknown error'}. Please check your JupiterOne API credentials and connection.`,
330
+ },
331
+ ],
332
+ isError: true,
333
+ };
334
+ }
335
+ },
270
336
  });
271
337
  // Tool: Get dashboards
272
- this.server.tool('get-dashboards', {}, async () => {
273
- try {
274
- const dashboards = await this.client.getDashboards();
275
- return {
276
- content: [
277
- {
278
- type: 'text',
279
- text: JSON.stringify({
280
- total: dashboards.length,
281
- dashboards: dashboards.map((dashboard) => ({
338
+ this.registerTool({
339
+ name: 'get-dashboards',
340
+ description: (0, load_description_js_1.loadDescription)('get-dashboards.md'),
341
+ schema: {},
342
+ handler: async (_, client) => {
343
+ try {
344
+ const dashboards = await client.getDashboards();
345
+ return {
346
+ content: [
347
+ {
348
+ type: 'text',
349
+ text: JSON.stringify({
350
+ total: dashboards.length,
351
+ dashboards: dashboards.map((dashboard) => ({
352
+ id: dashboard.id,
353
+ name: dashboard.name,
354
+ category: dashboard.category,
355
+ supportedUseCase: dashboard.supportedUseCase,
356
+ isJ1ManagedBoard: dashboard.isJ1ManagedBoard,
357
+ resourceGroupId: dashboard.resourceGroupId,
358
+ starred: dashboard.starred,
359
+ lastUpdated: dashboard._timeUpdated,
360
+ createdAt: dashboard._createdAt,
361
+ prerequisites: dashboard.prerequisites
362
+ ? {
363
+ prerequisitesMet: dashboard.prerequisites.prerequisitesMet,
364
+ preRequisitesGroupsFulfilled: dashboard.prerequisites.preRequisitesGroupsFulfilled,
365
+ preRequisitesGroupsRequired: dashboard.prerequisites.preRequisitesGroupsRequired,
366
+ }
367
+ : null,
368
+ })),
369
+ }, null, 2),
370
+ },
371
+ ],
372
+ };
373
+ }
374
+ catch (error) {
375
+ return {
376
+ content: [
377
+ {
378
+ type: 'text',
379
+ text: `Error getting dashboards: ${error instanceof Error ? error.message : 'Unknown error'}`,
380
+ },
381
+ ],
382
+ isError: true,
383
+ };
384
+ }
385
+ },
386
+ });
387
+ // Tool: Create dashboard
388
+ this.registerTool({
389
+ name: 'create-dashboard',
390
+ description: (0, load_description_js_1.loadDescription)('create-dashboard.md'),
391
+ schema: {
392
+ name: zod_1.z.string(),
393
+ type: zod_1.z.string(),
394
+ },
395
+ handler: async ({ name, type }, client) => {
396
+ try {
397
+ const result = await client.createDashboard({ name, type });
398
+ // Get account info to construct the URL
399
+ const accountInfo = await client.getAccountInfo();
400
+ const dashboardUrl = client.dashboardService.constructDashboardUrl(result.id, accountInfo.subdomain);
401
+ return {
402
+ content: [
403
+ {
404
+ type: 'text',
405
+ text: JSON.stringify({
406
+ id: result.id,
407
+ name,
408
+ type,
409
+ url: dashboardUrl,
410
+ }, null, 2),
411
+ },
412
+ ],
413
+ };
414
+ }
415
+ catch (error) {
416
+ return {
417
+ content: [
418
+ {
419
+ type: 'text',
420
+ text: `Error creating dashboard: ${error instanceof Error ? error.message : 'Unknown error'}`,
421
+ },
422
+ ],
423
+ isError: true,
424
+ };
425
+ }
426
+ },
427
+ });
428
+ // Tool: Get dashboard details
429
+ this.registerTool({
430
+ name: 'get-dashboard-details',
431
+ description: (0, load_description_js_1.loadDescription)('get-dashboard-details.md'),
432
+ schema: {
433
+ dashboardId: zod_1.z.string(),
434
+ },
435
+ handler: async ({ dashboardId }, client) => {
436
+ try {
437
+ const dashboard = await client.getDashboard(dashboardId);
438
+ return {
439
+ content: [
440
+ {
441
+ type: 'text',
442
+ text: JSON.stringify({
282
443
  id: dashboard.id,
283
444
  name: dashboard.name,
284
445
  category: dashboard.category,
285
446
  supportedUseCase: dashboard.supportedUseCase,
286
447
  isJ1ManagedBoard: dashboard.isJ1ManagedBoard,
448
+ published: dashboard.published,
449
+ publishedToUserIds: dashboard.publishedToUserIds,
450
+ publishedToGroupIds: dashboard.publishedToGroupIds,
451
+ groupIds: dashboard.groupIds,
452
+ userIds: dashboard.userIds,
453
+ scopeFilters: dashboard.scopeFilters,
287
454
  resourceGroupId: dashboard.resourceGroupId,
288
455
  starred: dashboard.starred,
289
456
  lastUpdated: dashboard._timeUpdated,
@@ -295,983 +462,963 @@ export class JupiterOneMcpServer {
295
462
  preRequisitesGroupsRequired: dashboard.prerequisites.preRequisitesGroupsRequired,
296
463
  }
297
464
  : null,
298
- })),
299
- }, null, 2),
300
- },
301
- ],
302
- };
303
- }
304
- catch (error) {
305
- return {
306
- content: [
307
- {
308
- type: 'text',
309
- text: `Error getting dashboards: ${error instanceof Error ? error.message : 'Unknown error'}`,
310
- },
311
- ],
312
- isError: true,
313
- };
314
- }
315
- });
316
- // Tool: Create dashboard
317
- this.server.tool('create-dashboard', loadDescription('create-dashboard.md'), {
318
- name: z.string(),
319
- type: z.string(),
320
- }, async ({ name, type }) => {
321
- try {
322
- const result = await this.client.createDashboard({ name, type });
323
- return {
324
- content: [
325
- {
326
- type: 'text',
327
- text: JSON.stringify({
328
- id: result.id,
329
- name,
330
- type,
331
- }, null, 2),
332
- },
333
- ],
334
- };
335
- }
336
- catch (error) {
337
- return {
338
- content: [
339
- {
340
- type: 'text',
341
- text: `Error creating dashboard: ${error instanceof Error ? error.message : 'Unknown error'}`,
342
- },
343
- ],
344
- isError: true,
345
- };
346
- }
347
- });
348
- // Tool: Get dashboard details
349
- this.server.tool('get-dashboard-details', {
350
- dashboardId: z.string(),
351
- }, async ({ dashboardId }) => {
352
- try {
353
- const dashboard = await this.client.getDashboard(dashboardId);
354
- return {
355
- content: [
356
- {
357
- type: 'text',
358
- text: JSON.stringify({
359
- id: dashboard.id,
360
- name: dashboard.name,
361
- category: dashboard.category,
362
- supportedUseCase: dashboard.supportedUseCase,
363
- isJ1ManagedBoard: dashboard.isJ1ManagedBoard,
364
- published: dashboard.published,
365
- publishedToUserIds: dashboard.publishedToUserIds,
366
- publishedToGroupIds: dashboard.publishedToGroupIds,
367
- groupIds: dashboard.groupIds,
368
- userIds: dashboard.userIds,
369
- scopeFilters: dashboard.scopeFilters,
370
- resourceGroupId: dashboard.resourceGroupId,
371
- starred: dashboard.starred,
372
- lastUpdated: dashboard._timeUpdated,
373
- createdAt: dashboard._createdAt,
374
- prerequisites: dashboard.prerequisites
375
- ? {
376
- prerequisitesMet: dashboard.prerequisites.prerequisitesMet,
377
- preRequisitesGroupsFulfilled: dashboard.prerequisites.preRequisitesGroupsFulfilled,
378
- preRequisitesGroupsRequired: dashboard.prerequisites.preRequisitesGroupsRequired,
379
- }
380
- : null,
381
- parameters: dashboard.parameters.map((param) => ({
382
- id: param.id,
383
- label: param.label,
384
- name: param.name,
385
- type: param.type,
386
- valueType: param.valueType,
387
- default: param.default,
388
- options: param.options,
389
- requireValue: param.requireValue,
390
- disableCustomInput: param.disableCustomInput,
391
- })),
392
- widgets: dashboard.widgets.map((widget) => ({
393
- id: widget.id,
394
- title: widget.title,
395
- description: widget.description,
396
- type: widget.type,
397
- questionId: widget.questionId,
398
- noResultMessage: widget.noResultMessage,
399
- includeDeleted: widget.includeDeleted,
400
- config: {
401
- queries: widget.config.queries.map((query) => ({
402
- id: query.id,
403
- name: query.name,
404
- query: query.query,
405
- })),
406
- settings: widget.config.settings,
407
- postQueryFilters: widget.config.postQueryFilters,
408
- disableQueryPolicyFilters: widget.config.disableQueryPolicyFilters,
409
- },
410
- })),
411
- layouts: {
412
- xs: dashboard.layouts.xs.map((item) => ({
413
- i: item.i,
414
- x: item.x,
415
- y: item.y,
416
- w: item.w,
417
- h: item.h,
418
- static: item.static,
419
- moved: item.moved,
420
- })),
421
- sm: dashboard.layouts.sm.map((item) => ({
422
- i: item.i,
423
- x: item.x,
424
- y: item.y,
425
- w: item.w,
426
- h: item.h,
427
- static: item.static,
428
- moved: item.moved,
429
- })),
430
- md: dashboard.layouts.md.map((item) => ({
431
- i: item.i,
432
- x: item.x,
433
- y: item.y,
434
- w: item.w,
435
- h: item.h,
436
- static: item.static,
437
- moved: item.moved,
438
- })),
439
- lg: dashboard.layouts.lg.map((item) => ({
440
- i: item.i,
441
- x: item.x,
442
- y: item.y,
443
- w: item.w,
444
- h: item.h,
445
- static: item.static,
446
- moved: item.moved,
465
+ parameters: dashboard.parameters.map((param) => ({
466
+ id: param.id,
467
+ label: param.label,
468
+ name: param.name,
469
+ type: param.type,
470
+ valueType: param.valueType,
471
+ default: param.default,
472
+ options: param.options,
473
+ requireValue: param.requireValue,
474
+ disableCustomInput: param.disableCustomInput,
447
475
  })),
448
- xl: dashboard.layouts.xl.map((item) => ({
449
- i: item.i,
450
- x: item.x,
451
- y: item.y,
452
- w: item.w,
453
- h: item.h,
454
- static: item.static,
455
- moved: item.moved,
476
+ widgets: dashboard.widgets.map((widget) => ({
477
+ id: widget.id,
478
+ title: widget.title,
479
+ description: widget.description,
480
+ type: widget.type,
481
+ questionId: widget.questionId,
482
+ noResultMessage: widget.noResultMessage,
483
+ includeDeleted: widget.includeDeleted,
484
+ config: {
485
+ queries: widget.config.queries.map((query) => ({
486
+ id: query.id,
487
+ name: query.name,
488
+ query: query.query,
489
+ })),
490
+ settings: widget.config.settings,
491
+ postQueryFilters: widget.config.postQueryFilters,
492
+ disableQueryPolicyFilters: widget.config.disableQueryPolicyFilters,
493
+ },
456
494
  })),
457
- },
458
- }, null, 2),
459
- },
460
- ],
461
- };
462
- }
463
- catch (error) {
464
- return {
465
- content: [
466
- {
467
- type: 'text',
468
- text: `Error getting dashboard details: ${error instanceof Error ? error.message : 'Unknown error'}`,
469
- },
470
- ],
471
- isError: true,
472
- };
473
- }
495
+ layouts: {
496
+ xs: dashboard.layouts.xs.map((item) => ({
497
+ i: item.i,
498
+ x: item.x,
499
+ y: item.y,
500
+ w: item.w,
501
+ h: item.h,
502
+ static: item.static,
503
+ moved: item.moved,
504
+ })),
505
+ sm: dashboard.layouts.sm.map((item) => ({
506
+ i: item.i,
507
+ x: item.x,
508
+ y: item.y,
509
+ w: item.w,
510
+ h: item.h,
511
+ static: item.static,
512
+ moved: item.moved,
513
+ })),
514
+ md: dashboard.layouts.md.map((item) => ({
515
+ i: item.i,
516
+ x: item.x,
517
+ y: item.y,
518
+ w: item.w,
519
+ h: item.h,
520
+ static: item.static,
521
+ moved: item.moved,
522
+ })),
523
+ lg: dashboard.layouts.lg.map((item) => ({
524
+ i: item.i,
525
+ x: item.x,
526
+ y: item.y,
527
+ w: item.w,
528
+ h: item.h,
529
+ static: item.static,
530
+ moved: item.moved,
531
+ })),
532
+ xl: dashboard.layouts.xl.map((item) => ({
533
+ i: item.i,
534
+ x: item.x,
535
+ y: item.y,
536
+ w: item.w,
537
+ h: item.h,
538
+ static: item.static,
539
+ moved: item.moved,
540
+ })),
541
+ },
542
+ }, null, 2),
543
+ },
544
+ ],
545
+ };
546
+ }
547
+ catch (error) {
548
+ return {
549
+ content: [
550
+ {
551
+ type: 'text',
552
+ text: `Error getting dashboard details: ${error instanceof Error ? error.message : 'Unknown error'}`,
553
+ },
554
+ ],
555
+ isError: true,
556
+ };
557
+ }
558
+ },
474
559
  });
475
560
  // Tool: Get integration definitions
476
- this.server.tool('get-integration-definitions', loadDescription('get-integration-definitions.md'), {
477
- cursor: z.string().optional().describe('Optional cursor for pagination'),
478
- includeConfig: z.boolean().optional().describe('Whether to include configuration fields'),
479
- }, async ({ cursor, includeConfig }) => {
480
- try {
481
- const definitions = await this.client.getIntegrationDefinitions(cursor, includeConfig);
482
- return {
483
- content: [
484
- {
485
- type: 'text',
486
- text: JSON.stringify({
487
- total: definitions.definitions.length,
488
- definitions: definitions.definitions.map((def) => ({
489
- id: def.id,
490
- name: def.name,
491
- type: def.type,
492
- title: def.title,
493
- displayMode: def.displayMode,
494
- integrationType: def.integrationType,
495
- integrationClass: def.integrationClass,
496
- integrationCategory: def.integrationCategory,
497
- beta: def.beta,
498
- docsWebLink: def.docsWebLink,
499
- repoWebLink: def.repoWebLink,
500
- invocationPaused: def.invocationPaused,
501
- managedExecutionDisabled: def.managedExecutionDisabled,
502
- managedCreateDisabled: def.managedCreateDisabled,
503
- managedDeleteDisabled: def.managedDeleteDisabled,
504
- totalInstanceCount: def.totalInstanceCount,
505
- description: def.description,
506
- provisioningType: def.provisioningType,
507
- customDefinitionType: def.customDefinitionType,
508
- integrationPlatformFeatures: def.integrationPlatformFeatures,
509
- configFields: def.configFields,
510
- authSections: def.authSections,
511
- configSections: def.configSections,
512
- })),
513
- pageInfo: definitions.pageInfo,
514
- }, null, 2),
515
- },
516
- ],
517
- };
518
- }
519
- catch (error) {
520
- return {
521
- content: [
522
- {
523
- type: 'text',
524
- text: `Error getting integration definitions: ${error instanceof Error ? error.message : 'Unknown error'}`,
525
- },
526
- ],
527
- isError: true,
528
- };
529
- }
561
+ this.registerTool({
562
+ name: 'get-integration-definitions',
563
+ description: (0, load_description_js_1.loadDescription)('get-integration-definitions.md'),
564
+ schema: {
565
+ cursor: zod_1.z.string().optional().describe('Optional cursor for pagination'),
566
+ includeConfig: zod_1.z.boolean().optional().describe('Whether to include configuration fields'),
567
+ },
568
+ handler: async ({ cursor, includeConfig }, client) => {
569
+ try {
570
+ const definitions = await client.getIntegrationDefinitions(cursor, includeConfig);
571
+ return {
572
+ content: [
573
+ {
574
+ type: 'text',
575
+ text: JSON.stringify({
576
+ total: definitions.definitions.length,
577
+ definitions: definitions.definitions.map((def) => ({
578
+ id: def.id,
579
+ name: def.name,
580
+ type: def.type,
581
+ title: def.title,
582
+ displayMode: def.displayMode,
583
+ integrationType: def.integrationType,
584
+ integrationClass: def.integrationClass,
585
+ integrationCategory: def.integrationCategory,
586
+ beta: def.beta,
587
+ docsWebLink: def.docsWebLink,
588
+ repoWebLink: def.repoWebLink,
589
+ invocationPaused: def.invocationPaused,
590
+ managedExecutionDisabled: def.managedExecutionDisabled,
591
+ managedCreateDisabled: def.managedCreateDisabled,
592
+ managedDeleteDisabled: def.managedDeleteDisabled,
593
+ totalInstanceCount: def.totalInstanceCount,
594
+ description: def.description,
595
+ provisioningType: def.provisioningType,
596
+ customDefinitionType: def.customDefinitionType,
597
+ integrationPlatformFeatures: def.integrationPlatformFeatures,
598
+ configFields: def.configFields,
599
+ authSections: def.authSections,
600
+ configSections: def.configSections,
601
+ })),
602
+ pageInfo: definitions.pageInfo,
603
+ }, null, 2),
604
+ },
605
+ ],
606
+ };
607
+ }
608
+ catch (error) {
609
+ return {
610
+ content: [
611
+ {
612
+ type: 'text',
613
+ text: `Error getting integration definitions: ${error instanceof Error ? error.message : 'Unknown error'}`,
614
+ },
615
+ ],
616
+ isError: true,
617
+ };
618
+ }
619
+ },
530
620
  });
531
621
  // Tool: Get integration instances
532
- this.server.tool('get-integration-instances', loadDescription('get-integration-instances.md'), {
533
- definitionId: z
534
- .string()
535
- .optional()
536
- .describe('Optional ID to filter instances by definition'),
537
- limit: z
538
- .number()
539
- .min(1)
540
- .max(1000)
541
- .optional()
542
- .describe('Optional limit for number of instances to return'),
543
- }, async ({ definitionId, limit }) => {
544
- try {
545
- const instances = await this.client.getIntegrationInstances(definitionId, undefined, limit);
546
- return {
547
- content: [
548
- {
549
- type: 'text',
550
- text: JSON.stringify({
551
- total: instances.instances.length,
552
- instances: instances.instances.map((instance) => ({
553
- id: instance.id,
554
- name: instance.name,
555
- accountId: instance.accountId,
556
- sourceIntegrationInstanceId: instance.sourceIntegrationInstanceId,
557
- pollingInterval: instance.pollingInterval,
558
- pollingIntervalCronExpression: instance.pollingIntervalCronExpression,
559
- integrationDefinitionId: instance.integrationDefinitionId,
560
- description: instance.description,
561
- config: instance.config,
562
- instanceRelationship: instance.instanceRelationship,
563
- resourceGroupId: instance.resourceGroupId,
564
- createdOn: instance.createdOn,
565
- createdBy: instance.createdBy,
566
- updatedOn: instance.updatedOn,
567
- updatedBy: instance.updatedBy,
568
- mostRecentJob: instance.mostRecentJob
569
- ? {
570
- status: instance.mostRecentJob.status,
571
- hasSkippedSteps: instance.mostRecentJob.hasSkippedSteps,
572
- createDate: instance.mostRecentJob.createDate,
573
- }
574
- : null,
575
- })),
576
- pageInfo: instances.pageInfo,
577
- }, null, 2),
578
- },
579
- ],
580
- };
581
- }
582
- catch (error) {
583
- return {
584
- content: [
585
- {
586
- type: 'text',
587
- text: `Error getting integration instances: ${error instanceof Error ? error.message : 'Unknown error'}`,
588
- },
589
- ],
590
- isError: true,
591
- };
592
- }
622
+ this.registerTool({
623
+ name: 'get-integration-instances',
624
+ description: (0, load_description_js_1.loadDescription)('get-integration-instances.md'),
625
+ schema: {
626
+ definitionId: zod_1.z
627
+ .string()
628
+ .optional()
629
+ .describe('Optional ID to filter instances by definition'),
630
+ limit: zod_1.z
631
+ .number()
632
+ .min(1)
633
+ .max(1000)
634
+ .optional()
635
+ .describe('Optional limit for number of instances to return'),
636
+ },
637
+ handler: async ({ definitionId, limit }, client) => {
638
+ try {
639
+ const instances = await client.getIntegrationInstances(definitionId, undefined, limit);
640
+ return {
641
+ content: [
642
+ {
643
+ type: 'text',
644
+ text: JSON.stringify({
645
+ total: instances.instances.length,
646
+ instances: instances.instances.map((instance) => ({
647
+ id: instance.id,
648
+ name: instance.name,
649
+ accountId: instance.accountId,
650
+ sourceIntegrationInstanceId: instance.sourceIntegrationInstanceId,
651
+ pollingInterval: instance.pollingInterval,
652
+ pollingIntervalCronExpression: instance.pollingIntervalCronExpression,
653
+ integrationDefinitionId: instance.integrationDefinitionId,
654
+ description: instance.description,
655
+ config: instance.config,
656
+ instanceRelationship: instance.instanceRelationship,
657
+ resourceGroupId: instance.resourceGroupId,
658
+ createdOn: instance.createdOn,
659
+ createdBy: instance.createdBy,
660
+ updatedOn: instance.updatedOn,
661
+ updatedBy: instance.updatedBy,
662
+ mostRecentJob: instance.mostRecentJob
663
+ ? {
664
+ status: instance.mostRecentJob.status,
665
+ hasSkippedSteps: instance.mostRecentJob.hasSkippedSteps,
666
+ createDate: instance.mostRecentJob.createDate,
667
+ }
668
+ : null,
669
+ })),
670
+ pageInfo: instances.pageInfo,
671
+ }, null, 2),
672
+ },
673
+ ],
674
+ };
675
+ }
676
+ catch (error) {
677
+ return {
678
+ content: [
679
+ {
680
+ type: 'text',
681
+ text: `Error getting integration instances: ${error instanceof Error ? error.message : 'Unknown error'}`,
682
+ },
683
+ ],
684
+ isError: true,
685
+ };
686
+ }
687
+ },
593
688
  });
594
689
  // Tool: Get integration jobs
595
- this.server.tool('get-integration-jobs', {
596
- status: z
597
- .enum(['PENDING', 'RUNNING', 'COMPLETED', 'FAILED', 'CANCELLED'])
598
- .optional()
599
- .describe('Optional status to filter jobs'),
600
- integrationInstanceId: z
601
- .string()
602
- .optional()
603
- .describe('Optional ID to filter jobs by instance'),
604
- integrationDefinitionId: z
605
- .string()
606
- .optional()
607
- .describe('Optional ID to filter jobs by definition'),
608
- integrationInstanceIds: z
609
- .array(z.string())
610
- .optional()
611
- .describe('Optional array of instance IDs to filter jobs'),
612
- size: z
613
- .number()
614
- .min(1)
615
- .max(1000)
616
- .optional()
617
- .describe('Optional size limit for number of jobs to return'),
618
- }, async ({ status, integrationInstanceId, integrationDefinitionId, integrationInstanceIds, size, }) => {
619
- try {
620
- const jobs = await this.client.getIntegrationJobs(status, integrationInstanceId, integrationDefinitionId, integrationInstanceIds, undefined, size);
621
- return {
622
- content: [
623
- {
624
- type: 'text',
625
- text: JSON.stringify({
626
- total: jobs.jobs.length,
627
- jobs: jobs.jobs.map((job) => ({
628
- id: job.id,
629
- status: job.status,
630
- integrationInstanceId: job.integrationInstanceId,
631
- createDate: job.createDate,
632
- endDate: job.endDate,
633
- hasSkippedSteps: job.hasSkippedSteps,
634
- integrationInstance: {
635
- id: job.integrationInstance.id,
636
- name: job.integrationInstance.name,
637
- },
638
- integrationDefinition: {
639
- id: job.integrationDefinition.id,
640
- title: job.integrationDefinition.title,
641
- integrationType: job.integrationDefinition.integrationType,
642
- },
643
- })),
644
- pageInfo: jobs.pageInfo,
645
- }, null, 2),
646
- },
647
- ],
648
- };
649
- }
650
- catch (error) {
651
- return {
652
- content: [
653
- {
654
- type: 'text',
655
- text: `Error getting integration jobs: ${error instanceof Error ? error.message : 'Unknown error'}`,
656
- },
657
- ],
658
- isError: true,
659
- };
660
- }
690
+ this.registerTool({
691
+ name: 'get-integration-jobs',
692
+ description: (0, load_description_js_1.loadDescription)('get-integration-jobs.md'),
693
+ schema: {
694
+ status: zod_1.z
695
+ .enum(['PENDING', 'RUNNING', 'COMPLETED', 'FAILED', 'CANCELLED'])
696
+ .optional()
697
+ .describe('Optional status to filter jobs'),
698
+ integrationInstanceId: zod_1.z
699
+ .string()
700
+ .optional()
701
+ .describe('Optional ID to filter jobs by instance'),
702
+ integrationDefinitionId: zod_1.z
703
+ .string()
704
+ .optional()
705
+ .describe('Optional ID to filter jobs by definition'),
706
+ integrationInstanceIds: zod_1.z
707
+ .array(zod_1.z.string())
708
+ .optional()
709
+ .describe('Optional array of instance IDs to filter jobs'),
710
+ size: zod_1.z
711
+ .number()
712
+ .min(1)
713
+ .max(1000)
714
+ .optional()
715
+ .describe('Optional size limit for number of jobs to return'),
716
+ },
717
+ handler: async ({ status, integrationInstanceId, integrationDefinitionId, integrationInstanceIds, size }, client) => {
718
+ try {
719
+ const jobs = await client.getIntegrationJobs(status, integrationInstanceId, integrationDefinitionId, integrationInstanceIds, undefined, size);
720
+ return {
721
+ content: [
722
+ {
723
+ type: 'text',
724
+ text: JSON.stringify({
725
+ total: jobs.jobs.length,
726
+ jobs: jobs.jobs.map((job) => ({
727
+ id: job.id,
728
+ status: job.status,
729
+ integrationInstanceId: job.integrationInstanceId,
730
+ createDate: job.createDate,
731
+ endDate: job.endDate,
732
+ hasSkippedSteps: job.hasSkippedSteps,
733
+ integrationInstance: job.integrationInstance,
734
+ integrationDefinition: job.integrationDefinition,
735
+ })),
736
+ pageInfo: jobs.pageInfo,
737
+ }, null, 2),
738
+ },
739
+ ],
740
+ };
741
+ }
742
+ catch (error) {
743
+ return {
744
+ content: [
745
+ {
746
+ type: 'text',
747
+ text: `Error getting integration jobs: ${error instanceof Error ? error.message : 'Unknown error'}`,
748
+ },
749
+ ],
750
+ isError: true,
751
+ };
752
+ }
753
+ },
661
754
  });
662
755
  // Tool: Create inline question rule instance
663
- this.server.tool('create-inline-question-rule', loadDescription('create-inline-question-rule.md'), {
664
- name: z.string().describe('Name of the rule'),
665
- description: z.string().describe('Description of the rule'),
666
- notifyOnFailure: z.boolean().optional().describe('Whether to notify on failure'),
667
- triggerActionsOnNewEntitiesOnly: z
668
- .boolean()
669
- .optional()
670
- .describe('Whether to trigger actions only on new entities'),
671
- ignorePreviousResults: z
672
- .boolean()
673
- .optional()
674
- .describe('Whether to ignore previous results'),
675
- pollingInterval: z
676
- .enum([
677
- 'DISABLED',
678
- 'THIRTY_MINUTES',
679
- 'ONE_HOUR',
680
- 'FOUR_HOURS',
681
- 'EIGHT_HOURS',
682
- 'TWELVE_HOURS',
683
- 'ONE_DAY',
684
- 'ONE_WEEK',
685
- ])
686
- .describe('How frequently to evaluate the rule'),
687
- outputs: z.array(z.string()).describe('Output fields from the rule evaluation'),
688
- specVersion: z.number().optional().describe('Specification version'),
689
- tags: z.array(z.string()).optional().describe('Tags for categorizing the rule'),
690
- templates: z.record(z.any()).optional().describe('Template variables'),
691
- queries: z
692
- .array(z.object({
693
- query: z.string().describe('J1QL query string'),
694
- name: z.string().describe('Name identifier for the query'),
695
- version: z.string().optional().describe('Version of the query'),
696
- includeDeleted: z
756
+ this.registerTool({
757
+ name: 'create-inline-question-rule',
758
+ description: (0, load_description_js_1.loadDescription)('create-inline-question-rule.md'),
759
+ schema: {
760
+ name: zod_1.z.string().describe('Name of the rule'),
761
+ description: zod_1.z.string().describe('Description of the rule'),
762
+ notifyOnFailure: zod_1.z.boolean().optional().describe('Whether to notify on failure'),
763
+ triggerActionsOnNewEntitiesOnly: zod_1.z
764
+ .boolean()
765
+ .optional()
766
+ .describe('Whether to trigger actions only on new entities'),
767
+ ignorePreviousResults: zod_1.z
697
768
  .boolean()
698
769
  .optional()
699
- .describe('Whether to include deleted entities'),
700
- }))
701
- .describe('J1QL queries that define what entities to match'),
702
- operations: z
703
- .array(z.object({
704
- when: z
770
+ .describe('Whether to ignore previous results'),
771
+ pollingInterval: zod_1.z
772
+ .enum([
773
+ 'DISABLED',
774
+ 'THIRTY_MINUTES',
775
+ 'ONE_HOUR',
776
+ 'FOUR_HOURS',
777
+ 'EIGHT_HOURS',
778
+ 'TWELVE_HOURS',
779
+ 'ONE_DAY',
780
+ 'ONE_WEEK',
781
+ ])
782
+ .describe('How frequently to evaluate the rule'),
783
+ outputs: zod_1.z.array(zod_1.z.string()).describe('Output fields from the rule evaluation'),
784
+ specVersion: zod_1.z.number().optional().describe('Specification version'),
785
+ tags: zod_1.z.array(zod_1.z.string()).optional().describe('Tags for categorizing the rule'),
786
+ templates: zod_1.z.record(zod_1.z.any()).optional().describe('Template variables'),
787
+ question: zod_1.z
705
788
  .object({
706
- type: z.literal('FILTER'),
707
- condition: z.array(z.any()).describe('Filter condition array'),
789
+ queries: zod_1.z.array(zod_1.z.object({
790
+ query: zod_1.z.string().describe('J1QL query string'),
791
+ name: zod_1.z.string().describe('Name identifier for the query'),
792
+ version: zod_1.z.string().optional().describe('Version of the query'),
793
+ includeDeleted: zod_1.z.boolean().describe('Whether to include deleted entities'),
794
+ })),
708
795
  })
709
- .describe('Condition that triggers the actions'),
710
- actions: z
711
- .array(z.object({
712
- id: z.string().optional(),
713
- type: z
714
- .string()
715
- .describe('Action type (e.g., SET_PROPERTY, CREATE_ALERT, SEND_EMAIL)'),
716
- targetProperty: z
717
- .string()
718
- .optional()
719
- .describe('Property to set (for SET_PROPERTY actions)'),
720
- targetValue: z
721
- .any()
722
- .optional()
723
- .describe('Value to set (for SET_PROPERTY actions)'),
724
- integrationInstanceId: z
725
- .string()
726
- .optional()
727
- .describe('ID of the integration instance for integration actions'),
728
- recipients: z
729
- .array(z.string())
730
- .optional()
731
- .describe('Email recipients for SEND_EMAIL action'),
732
- body: z.string().optional().describe('Message body for email/slack actions'),
733
- channels: z
734
- .array(z.string())
735
- .optional()
736
- .describe('Slack channels for SEND_SLACK_MESSAGE action'),
737
- bucket: z.string().optional().describe('S3 bucket name for SEND_TO_S3 action'),
738
- region: z.string().optional().describe('AWS region for SEND_TO_S3 action'),
739
- data: z.any().optional().describe('Additional data for actions'),
740
- entityClass: z
741
- .string()
742
- .optional()
743
- .describe('Entity class for CREATE_JIRA_TICKET action'),
744
- summary: z
745
- .string()
746
- .optional()
747
- .describe('Summary for CREATE_JIRA_TICKET action'),
748
- issueType: z
749
- .string()
750
- .optional()
751
- .describe('Issue type for CREATE_JIRA_TICKET action'),
752
- project: z
753
- .string()
754
- .optional()
755
- .describe('Project key for CREATE_JIRA_TICKET action'),
756
- updateContentOnChanges: z
757
- .boolean()
758
- .optional()
759
- .describe('Whether to update content on changes for CREATE_JIRA_TICKET action'),
760
- additionalFields: z
761
- .any()
762
- .optional()
763
- .describe('Additional fields for CREATE_JIRA_TICKET action'),
796
+ .describe('Question configuration'),
797
+ labels: zod_1.z
798
+ .array(zod_1.z.object({
799
+ labelName: zod_1.z.string(),
800
+ labelValue: zod_1.z.string().nullable(),
801
+ }))
802
+ .describe('Labels for the rule'),
803
+ operations: zod_1.z
804
+ .array(zod_1.z.object({
805
+ when: zod_1.z
806
+ .object({
807
+ type: zod_1.z.literal('FILTER'),
808
+ condition: zod_1.z
809
+ .array(zod_1.z.union([zod_1.z.string(), zod_1.z.number(), zod_1.z.array(zod_1.z.union([zod_1.z.string(), zod_1.z.number()]))]))
810
+ .describe('Filter condition array (e.g., ["AND", ["queries.query0.total", ">", 0]])'),
811
+ })
812
+ .describe('Condition that triggers the actions'),
813
+ actions: zod_1.z
814
+ .array(zod_1.z.object({
815
+ id: zod_1.z.string().optional(),
816
+ type: zod_1.z
817
+ .string()
818
+ .describe('Action type (e.g., SET_PROPERTY, CREATE_ALERT, SEND_EMAIL)'),
819
+ targetProperty: zod_1.z
820
+ .string()
821
+ .optional()
822
+ .describe('Property to set (for SET_PROPERTY actions)'),
823
+ targetValue: zod_1.z
824
+ .any()
825
+ .optional()
826
+ .describe('Value to set (for SET_PROPERTY actions)'),
827
+ integrationInstanceId: zod_1.z
828
+ .string()
829
+ .optional()
830
+ .describe('ID of the integration instance for integration actions'),
831
+ recipients: zod_1.z
832
+ .array(zod_1.z.string())
833
+ .optional()
834
+ .describe('Email recipients for SEND_EMAIL action'),
835
+ body: zod_1.z.string().optional().describe('Message body for email/slack actions'),
836
+ channels: zod_1.z
837
+ .array(zod_1.z.string())
838
+ .optional()
839
+ .describe('Slack channels for SEND_SLACK_MESSAGE action'),
840
+ bucket: zod_1.z.string().optional().describe('S3 bucket name for SEND_TO_S3 action'),
841
+ region: zod_1.z.string().optional().describe('AWS region for SEND_TO_S3 action'),
842
+ data: zod_1.z.any().optional().describe('Additional data for actions'),
843
+ entityClass: zod_1.z
844
+ .string()
845
+ .optional()
846
+ .describe('Entity class for CREATE_JIRA_TICKET action'),
847
+ summary: zod_1.z
848
+ .string()
849
+ .optional()
850
+ .describe('Summary for CREATE_JIRA_TICKET action'),
851
+ issueType: zod_1.z
852
+ .string()
853
+ .optional()
854
+ .describe('Issue type for CREATE_JIRA_TICKET action'),
855
+ project: zod_1.z
856
+ .string()
857
+ .optional()
858
+ .describe('Project key for CREATE_JIRA_TICKET action'),
859
+ updateContentOnChanges: zod_1.z
860
+ .boolean()
861
+ .optional()
862
+ .describe('Whether to update content on changes for CREATE_JIRA_TICKET action'),
863
+ additionalFields: zod_1.z
864
+ .any()
865
+ .optional()
866
+ .describe('Additional fields for CREATE_JIRA_TICKET action'),
867
+ }))
868
+ .describe('Actions to take when condition is met'),
764
869
  }))
765
- .describe('Actions to take when condition is met'),
766
- }))
767
- .describe('Operations to perform when conditions are met'),
768
- }, async ({ name, description, notifyOnFailure, triggerActionsOnNewEntitiesOnly, ignorePreviousResults, pollingInterval, outputs, specVersion, tags, templates, queries, operations, }) => {
769
- try {
770
- // Validate all queries before creating the rule
771
- const validationResults = await this.validateQueries(queries);
772
- if (validationResults.length > 0) {
773
- return this.createValidationErrorResponse(validationResults);
870
+ .describe('Operations to perform when conditions are met'),
871
+ },
872
+ handler: async ({ name, description, notifyOnFailure, triggerActionsOnNewEntitiesOnly, ignorePreviousResults, pollingInterval, outputs, specVersion, labels, tags, templates, question, operations, }, client, validator) => {
873
+ try {
874
+ // Validate all queries before creating the rule
875
+ const validationResults = await this.validateQueries(question.queries, validator);
876
+ if (validationResults.length > 0) {
877
+ return this.createValidationErrorResponse(validationResults);
878
+ }
879
+ const instance = {
880
+ name,
881
+ description,
882
+ notifyOnFailure,
883
+ triggerActionsOnNewEntitiesOnly,
884
+ ignorePreviousResults,
885
+ pollingInterval,
886
+ outputs,
887
+ specVersion,
888
+ labels,
889
+ tags,
890
+ templates,
891
+ question,
892
+ operations,
893
+ };
894
+ const result = await client.createInlineQuestionRuleInstance(instance);
895
+ // Get account info to construct the URL
896
+ const accountInfo = await client.getAccountInfo();
897
+ const ruleUrl = client.ruleService.constructRuleUrl(result.id, accountInfo.subdomain);
898
+ return {
899
+ content: [
900
+ {
901
+ type: 'text',
902
+ text: JSON.stringify({
903
+ success: true,
904
+ rule: {
905
+ id: result.id,
906
+ name: result.name,
907
+ description: result.description,
908
+ version: result.version,
909
+ pollingInterval: result.pollingInterval,
910
+ outputs: result.outputs,
911
+ specVersion: result.specVersion,
912
+ notifyOnFailure: result.notifyOnFailure,
913
+ triggerActionsOnNewEntitiesOnly: result.triggerActionsOnNewEntitiesOnly,
914
+ ignorePreviousResults: result.ignorePreviousResults,
915
+ tags: result.tags,
916
+ question: result.question,
917
+ operations: result.operations,
918
+ latestAlertId: result.latestAlertId,
919
+ latestAlertIsActive: result.latestAlertIsActive,
920
+ url: ruleUrl,
921
+ },
922
+ }, null, 2),
923
+ },
924
+ ],
925
+ };
774
926
  }
775
- const instance = {
776
- name,
777
- description,
778
- notifyOnFailure,
779
- triggerActionsOnNewEntitiesOnly,
780
- ignorePreviousResults,
781
- pollingInterval,
782
- outputs,
783
- specVersion,
784
- tags,
785
- templates,
786
- question: {
787
- queries,
788
- },
789
- operations,
790
- };
791
- const result = await this.client.createInlineQuestionRuleInstance(instance);
792
- return {
793
- content: [
794
- {
795
- type: 'text',
796
- text: JSON.stringify({
797
- success: true,
798
- rule: {
799
- id: result.id,
800
- name: result.name,
801
- description: result.description,
802
- version: result.version,
803
- pollingInterval: result.pollingInterval,
804
- outputs: result.outputs,
805
- specVersion: result.specVersion,
806
- notifyOnFailure: result.notifyOnFailure,
807
- triggerActionsOnNewEntitiesOnly: result.triggerActionsOnNewEntitiesOnly,
808
- ignorePreviousResults: result.ignorePreviousResults,
809
- tags: result.tags,
810
- question: result.question,
811
- operations: result.operations,
812
- latestAlertId: result.latestAlertId,
813
- latestAlertIsActive: result.latestAlertIsActive,
814
- },
815
- }, null, 2),
816
- },
817
- ],
818
- };
819
- }
820
- catch (error) {
821
- return {
822
- content: [
823
- {
824
- type: 'text',
825
- text: `Error creating inline question rule: ${error instanceof Error ? error.message : 'Unknown error'}`,
826
- },
827
- ],
828
- isError: true,
829
- };
830
- }
927
+ catch (error) {
928
+ return {
929
+ content: [
930
+ {
931
+ type: 'text',
932
+ text: `Error creating inline question rule: ${error instanceof Error ? error.message : 'Unknown error'}`,
933
+ },
934
+ ],
935
+ isError: true,
936
+ };
937
+ }
938
+ },
831
939
  });
832
940
  // Tool: Update inline question rule instance
833
- this.server.tool('update-inline-question-rule', loadDescription('update-inline-question-rule.md'), {
834
- id: z.string().describe('ID of the rule to update'),
835
- name: z.string().describe('Name of the rule'),
836
- description: z.string().describe('Description of the rule'),
837
- notifyOnFailure: z.boolean().describe('Whether to notify on failure'),
838
- triggerActionsOnNewEntitiesOnly: z
839
- .boolean()
840
- .describe('Whether to trigger actions only on new entities'),
841
- ignorePreviousResults: z.boolean().describe('Whether to ignore previous results'),
842
- pollingInterval: z
843
- .enum([
844
- 'DISABLED',
845
- 'THIRTY_MINUTES',
846
- 'ONE_HOUR',
847
- 'FOUR_HOURS',
848
- 'EIGHT_HOURS',
849
- 'TWELVE_HOURS',
850
- 'ONE_DAY',
851
- 'ONE_WEEK',
852
- ])
853
- .describe('How frequently to evaluate the rule'),
854
- outputs: z.array(z.string()).describe('Output fields from the rule evaluation'),
855
- specVersion: z.number().describe('Specification version'),
856
- version: z.number().describe('Version of the rule'),
857
- tags: z.array(z.string()).describe('Tags for categorizing the rule'),
858
- templates: z.record(z.any()).describe('Template variables'),
859
- labels: z
860
- .array(z.object({
861
- labelName: z.string(),
862
- labelValue: z.string().nullable(),
863
- }))
864
- .describe('Labels for the rule'),
865
- resourceGroupId: z.string().nullable().describe('Resource group ID'),
866
- remediationSteps: z
867
- .string()
868
- .nullable()
869
- .describe('Steps to remediate issues found by the rule'),
870
- question: z
871
- .object({
872
- queries: z.array(z.object({
873
- query: z.string().describe('J1QL query string'),
874
- name: z.string().describe('Name identifier for the query'),
875
- version: z.string().optional().describe('Version of the query'),
876
- includeDeleted: z.boolean().describe('Whether to include deleted entities'),
877
- })),
878
- })
879
- .describe('Question configuration'),
880
- operations: z
881
- .array(z.object({
882
- when: z
941
+ this.registerTool({
942
+ name: 'update-inline-question-rule',
943
+ description: (0, load_description_js_1.loadDescription)('update-inline-question-rule.md'),
944
+ schema: {
945
+ id: zod_1.z.string().describe('ID of the rule to update'),
946
+ name: zod_1.z.string().describe('Name of the rule'),
947
+ description: zod_1.z.string().describe('Description of the rule'),
948
+ notifyOnFailure: zod_1.z.boolean().describe('Whether to notify on failure'),
949
+ triggerActionsOnNewEntitiesOnly: zod_1.z
950
+ .boolean()
951
+ .describe('Whether to trigger actions only on new entities'),
952
+ ignorePreviousResults: zod_1.z.boolean().describe('Whether to ignore previous results'),
953
+ pollingInterval: zod_1.z
954
+ .enum([
955
+ 'DISABLED',
956
+ 'THIRTY_MINUTES',
957
+ 'ONE_HOUR',
958
+ 'FOUR_HOURS',
959
+ 'EIGHT_HOURS',
960
+ 'TWELVE_HOURS',
961
+ 'ONE_DAY',
962
+ 'ONE_WEEK',
963
+ ])
964
+ .describe('How frequently to evaluate the rule'),
965
+ outputs: zod_1.z.array(zod_1.z.string()).describe('Output fields from the rule evaluation'),
966
+ specVersion: zod_1.z.number().describe('Specification version'),
967
+ tags: zod_1.z.array(zod_1.z.string()).describe('Tags for categorizing the rule'),
968
+ templates: zod_1.z.record(zod_1.z.any()).describe('Template variables'),
969
+ labels: zod_1.z
970
+ .array(zod_1.z.object({
971
+ labelName: zod_1.z.string(),
972
+ labelValue: zod_1.z.string().nullable(),
973
+ }))
974
+ .describe('Labels for the rule'),
975
+ resourceGroupId: zod_1.z.string().nullable().describe('Resource group ID'),
976
+ remediationSteps: zod_1.z
977
+ .string()
978
+ .nullable()
979
+ .describe('Steps to remediate issues found by the rule'),
980
+ question: zod_1.z
883
981
  .object({
884
- type: z.literal('FILTER'),
885
- condition: z.array(z.any()).describe('Filter condition array'),
982
+ queries: zod_1.z.array(zod_1.z.object({
983
+ query: zod_1.z.string().describe('J1QL query string'),
984
+ name: zod_1.z.string().describe('Name identifier for the query'),
985
+ version: zod_1.z.string().optional().describe('Version of the query'),
986
+ includeDeleted: zod_1.z.boolean().describe('Whether to include deleted entities'),
987
+ })),
886
988
  })
887
- .describe('Condition that triggers the actions'),
888
- actions: z.array(z.object({
889
- id: z.string().optional(),
890
- type: z.string().describe('Action type (e.g., SET_PROPERTY, CREATE_ALERT)'),
891
- targetProperty: z
892
- .string()
893
- .optional()
894
- .describe('Property to set (for SET_PROPERTY actions)'),
895
- targetValue: z
896
- .any()
897
- .optional()
898
- .describe('Value to set (for SET_PROPERTY actions)'),
899
- integrationInstanceId: z
900
- .string()
901
- .optional()
902
- .describe('ID of the integration instance for integration actions'),
903
- recipients: z
904
- .array(z.string())
905
- .optional()
906
- .describe('Email recipients for SEND_EMAIL action'),
907
- body: z.string().optional().describe('Message body for email/slack actions'),
908
- channels: z
909
- .array(z.string())
910
- .optional()
911
- .describe('Slack channels for SEND_SLACK_MESSAGE action'),
912
- bucket: z.string().optional().describe('S3 bucket name for SEND_TO_S3 action'),
913
- region: z.string().optional().describe('AWS region for SEND_TO_S3 action'),
914
- data: z.any().optional().describe('Additional data for actions'),
915
- entityClass: z
916
- .string()
917
- .optional()
918
- .describe('Entity class for CREATE_JIRA_TICKET action'),
919
- summary: z.string().optional().describe('Summary for CREATE_JIRA_TICKET action'),
920
- issueType: z
921
- .string()
922
- .optional()
923
- .describe('Issue type for CREATE_JIRA_TICKET action'),
924
- project: z.string().optional().describe('Project for CREATE_JIRA_TICKET action'),
925
- updateContentOnChanges: z
926
- .boolean()
927
- .optional()
928
- .describe('Whether to update content on changes for CREATE_JIRA_TICKET action'),
929
- additionalFields: z
930
- .any()
931
- .optional()
932
- .describe('Additional fields for CREATE_JIRA_TICKET action'),
933
- entities: z.string().optional().describe('Entities for TAG_ENTITIES action'),
934
- tags: z
935
- .array(z.object({
936
- name: z.string(),
937
- value: z.string().nullable(),
938
- }))
939
- .optional()
940
- .describe('Tags for TAG_ENTITIES action'),
941
- })),
942
- }))
943
- .describe('Operations that define when and what actions to take'),
944
- }, async ({ id, name, description, notifyOnFailure, triggerActionsOnNewEntitiesOnly, ignorePreviousResults, pollingInterval, outputs, specVersion, version, tags, templates, labels, resourceGroupId, remediationSteps, question, operations, }) => {
945
- try {
946
- // Validate all queries before updating the rule
947
- const validationResults = await this.validateQueries(question?.queries);
948
- if (validationResults.length > 0) {
949
- return this.createValidationErrorResponse(validationResults);
989
+ .describe('Question configuration'),
990
+ operations: zod_1.z
991
+ .array(zod_1.z.object({
992
+ when: zod_1.z
993
+ .object({
994
+ type: zod_1.z.literal('FILTER'),
995
+ condition: zod_1.z
996
+ .array(zod_1.z.union([zod_1.z.string(), zod_1.z.number(), zod_1.z.array(zod_1.z.union([zod_1.z.string(), zod_1.z.number()]))]))
997
+ .describe('Filter condition array (e.g., ["AND", ["queries.query0.total", ">", 0]])'),
998
+ })
999
+ .describe('Condition that triggers the actions'),
1000
+ actions: zod_1.z.array(zod_1.z.object({
1001
+ id: zod_1.z.string().optional(),
1002
+ type: zod_1.z.string().describe('Action type (e.g., SET_PROPERTY, CREATE_ALERT)'),
1003
+ targetProperty: zod_1.z
1004
+ .string()
1005
+ .optional()
1006
+ .describe('Property to set (for SET_PROPERTY actions)'),
1007
+ targetValue: zod_1.z
1008
+ .any()
1009
+ .optional()
1010
+ .describe('Value to set (for SET_PROPERTY actions)'),
1011
+ integrationInstanceId: zod_1.z
1012
+ .string()
1013
+ .optional()
1014
+ .describe('ID of the integration instance for integration actions'),
1015
+ recipients: zod_1.z
1016
+ .array(zod_1.z.string())
1017
+ .optional()
1018
+ .describe('Email recipients for SEND_EMAIL action'),
1019
+ body: zod_1.z.string().optional().describe('Message body for email/slack actions'),
1020
+ channels: zod_1.z
1021
+ .array(zod_1.z.string())
1022
+ .optional()
1023
+ .describe('Slack channels for SEND_SLACK_MESSAGE action'),
1024
+ bucket: zod_1.z.string().optional().describe('S3 bucket name for SEND_TO_S3 action'),
1025
+ region: zod_1.z.string().optional().describe('AWS region for SEND_TO_S3 action'),
1026
+ data: zod_1.z.any().optional().describe('Additional data for actions'),
1027
+ entityClass: zod_1.z
1028
+ .string()
1029
+ .optional()
1030
+ .describe('Entity class for CREATE_JIRA_TICKET action'),
1031
+ summary: zod_1.z.string().optional().describe('Summary for CREATE_JIRA_TICKET action'),
1032
+ issueType: zod_1.z
1033
+ .string()
1034
+ .optional()
1035
+ .describe('Issue type for CREATE_JIRA_TICKET action'),
1036
+ project: zod_1.z.string().optional().describe('Project for CREATE_JIRA_TICKET action'),
1037
+ updateContentOnChanges: zod_1.z
1038
+ .boolean()
1039
+ .optional()
1040
+ .describe('Whether to update content on changes for CREATE_JIRA_TICKET action'),
1041
+ additionalFields: zod_1.z
1042
+ .any()
1043
+ .optional()
1044
+ .describe('Additional fields for CREATE_JIRA_TICKET action'),
1045
+ entities: zod_1.z.string().optional().describe('Entities for TAG_ENTITIES action'),
1046
+ tags: zod_1.z
1047
+ .array(zod_1.z.object({
1048
+ name: zod_1.z.string(),
1049
+ value: zod_1.z.string().nullable(),
1050
+ }))
1051
+ .optional()
1052
+ .describe('Tags for TAG_ENTITIES action'),
1053
+ })),
1054
+ }))
1055
+ .describe('Operations that define when and what actions to take'),
1056
+ },
1057
+ handler: async ({ id, name, description, notifyOnFailure, triggerActionsOnNewEntitiesOnly, ignorePreviousResults, pollingInterval, outputs, specVersion, tags, templates, labels, resourceGroupId, remediationSteps, question, operations, }, client, validator) => {
1058
+ try {
1059
+ // Validate all queries before updating the rule
1060
+ const validationResults = await this.validateQueries(question?.queries, validator);
1061
+ if (validationResults.length > 0) {
1062
+ return this.createValidationErrorResponse(validationResults);
1063
+ }
1064
+ const instance = {
1065
+ id,
1066
+ name,
1067
+ description,
1068
+ notifyOnFailure,
1069
+ triggerActionsOnNewEntitiesOnly,
1070
+ ignorePreviousResults,
1071
+ pollingInterval,
1072
+ outputs,
1073
+ specVersion,
1074
+ labels,
1075
+ tags,
1076
+ templates,
1077
+ resourceGroupId,
1078
+ remediationSteps,
1079
+ question,
1080
+ operations,
1081
+ };
1082
+ const result = await client.updateInlineQuestionRuleInstance(instance);
1083
+ // Get account info to construct the URL
1084
+ const accountInfo = await client.getAccountInfo();
1085
+ const ruleUrl = client.ruleService.constructRuleUrl(result.id, accountInfo.subdomain);
1086
+ return {
1087
+ content: [
1088
+ {
1089
+ type: 'text',
1090
+ text: JSON.stringify({
1091
+ success: true,
1092
+ rule: {
1093
+ id: result.id,
1094
+ name: result.name,
1095
+ description: result.description,
1096
+ version: result.version,
1097
+ pollingInterval: result.pollingInterval,
1098
+ outputs: result.outputs,
1099
+ specVersion: result.specVersion,
1100
+ notifyOnFailure: result.notifyOnFailure,
1101
+ triggerActionsOnNewEntitiesOnly: result.triggerActionsOnNewEntitiesOnly,
1102
+ ignorePreviousResults: result.ignorePreviousResults,
1103
+ tags: result.tags,
1104
+ labels: result.labels,
1105
+ question: result.question,
1106
+ operations: result.operations,
1107
+ latestAlertId: result.latestAlertId,
1108
+ latestAlertIsActive: result.latestAlertIsActive,
1109
+ resourceGroupId: result.resourceGroupId,
1110
+ remediationSteps: result.remediationSteps,
1111
+ url: ruleUrl,
1112
+ },
1113
+ }, null, 2),
1114
+ },
1115
+ ],
1116
+ };
950
1117
  }
951
- const instance = {
952
- id,
953
- name,
954
- description,
955
- notifyOnFailure,
956
- triggerActionsOnNewEntitiesOnly,
957
- ignorePreviousResults,
958
- pollingInterval,
959
- outputs,
960
- specVersion,
961
- version,
962
- tags,
963
- templates,
964
- labels,
965
- resourceGroupId,
966
- remediationSteps,
967
- question,
968
- operations,
969
- };
970
- const result = await this.client.updateInlineQuestionRuleInstance(instance);
971
- return {
972
- content: [
973
- {
974
- type: 'text',
975
- text: JSON.stringify({
976
- success: true,
977
- rule: {
978
- id: result.id,
979
- name: result.name,
980
- description: result.description,
981
- version: result.version,
982
- pollingInterval: result.pollingInterval,
983
- outputs: result.outputs,
984
- specVersion: result.specVersion,
985
- notifyOnFailure: result.notifyOnFailure,
986
- triggerActionsOnNewEntitiesOnly: result.triggerActionsOnNewEntitiesOnly,
987
- ignorePreviousResults: result.ignorePreviousResults,
988
- tags: result.tags,
989
- labels: result.labels,
990
- question: result.question,
991
- operations: result.operations,
992
- latestAlertId: result.latestAlertId,
993
- latestAlertIsActive: result.latestAlertIsActive,
994
- resourceGroupId: result.resourceGroupId,
995
- remediationSteps: result.remediationSteps,
996
- },
997
- }, null, 2),
998
- },
999
- ],
1000
- };
1001
- }
1002
- catch (error) {
1003
- return {
1004
- content: [
1005
- {
1006
- type: 'text',
1007
- text: `Error updating inline question rule: ${error instanceof Error ? error.message : 'Unknown error'}`,
1008
- },
1009
- ],
1010
- isError: true,
1011
- };
1012
- }
1118
+ catch (error) {
1119
+ return {
1120
+ content: [
1121
+ {
1122
+ type: 'text',
1123
+ text: `Error updating inline question rule: ${error instanceof Error ? error.message : 'Unknown error'}`,
1124
+ },
1125
+ ],
1126
+ isError: true,
1127
+ };
1128
+ }
1129
+ },
1013
1130
  });
1014
1131
  // Add get-integration-job tool
1015
- this.server.tool('get-integration-job', {
1016
- integrationJobId: z.string().describe('ID of the job to get'),
1017
- integrationInstanceId: z.string().describe('ID of the instance the job belongs to'),
1018
- }, async ({ integrationJobId, integrationInstanceId }) => {
1019
- try {
1020
- const job = await this.client.getIntegrationJob(integrationJobId, integrationInstanceId);
1021
- return {
1022
- content: [
1023
- {
1024
- type: 'text',
1025
- text: JSON.stringify({
1026
- id: job.id,
1027
- status: job.status,
1028
- integrationInstanceId: job.integrationInstanceId,
1029
- createDate: job.createDate,
1030
- endDate: job.endDate,
1031
- hasSkippedSteps: job.hasSkippedSteps,
1032
- integrationInstance: job.integrationInstance,
1033
- integrationDefinition: job.integrationDefinition,
1034
- }, null, 2),
1035
- },
1036
- ],
1037
- };
1038
- }
1039
- catch (error) {
1040
- return {
1041
- content: [
1042
- {
1043
- type: 'text',
1044
- text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}`,
1045
- },
1046
- ],
1047
- isError: true,
1048
- };
1049
- }
1132
+ this.registerTool({
1133
+ name: 'get-integration-job',
1134
+ description: (0, load_description_js_1.loadDescription)('get-integration-job.md'),
1135
+ schema: {
1136
+ integrationJobId: zod_1.z.string().describe('ID of the job to get'),
1137
+ integrationInstanceId: zod_1.z.string().describe('ID of the instance the job belongs to'),
1138
+ },
1139
+ handler: async ({ integrationJobId, integrationInstanceId }, client) => {
1140
+ try {
1141
+ const job = await client.getIntegrationJob(integrationJobId, integrationInstanceId);
1142
+ return {
1143
+ content: [
1144
+ {
1145
+ type: 'text',
1146
+ text: JSON.stringify({
1147
+ id: job.id,
1148
+ status: job.status,
1149
+ integrationInstanceId: job.integrationInstanceId,
1150
+ createDate: job.createDate,
1151
+ endDate: job.endDate,
1152
+ hasSkippedSteps: job.hasSkippedSteps,
1153
+ integrationInstance: job.integrationInstance,
1154
+ integrationDefinition: job.integrationDefinition,
1155
+ }, null, 2),
1156
+ },
1157
+ ],
1158
+ };
1159
+ }
1160
+ catch (error) {
1161
+ return {
1162
+ content: [
1163
+ {
1164
+ type: 'text',
1165
+ text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}`,
1166
+ },
1167
+ ],
1168
+ isError: true,
1169
+ };
1170
+ }
1171
+ },
1050
1172
  });
1051
1173
  // Add get-integration-events tool
1052
- this.server.tool('get-integration-events', {
1053
- jobId: z.string().describe('ID of the job to get events for'),
1054
- integrationInstanceId: z.string().describe('ID of the instance the job belongs to'),
1055
- cursor: z.string().optional().describe('Optional cursor for pagination'),
1056
- size: z
1057
- .number()
1058
- .min(1)
1059
- .max(1000)
1060
- .optional()
1061
- .describe('Optional size limit for number of events to return (1-1000)'),
1062
- }, async ({ jobId, integrationInstanceId, cursor, size }) => {
1063
- try {
1064
- const events = await this.client.getIntegrationEvents(jobId, integrationInstanceId, cursor, size);
1065
- return {
1066
- content: [
1067
- {
1068
- type: 'text',
1069
- text: JSON.stringify({
1070
- events: events.events.map((event) => ({
1071
- id: event.id,
1072
- name: event.name,
1073
- description: event.description,
1074
- createDate: event.createDate,
1075
- jobId: event.jobId,
1076
- level: event.level,
1077
- eventCode: event.eventCode,
1078
- })),
1079
- pageInfo: events.pageInfo,
1080
- }, null, 2),
1081
- },
1082
- ],
1083
- };
1084
- }
1085
- catch (error) {
1086
- return {
1087
- content: [
1088
- {
1089
- type: 'text',
1090
- text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}`,
1091
- },
1092
- ],
1093
- isError: true,
1094
- };
1095
- }
1174
+ this.registerTool({
1175
+ name: 'get-integration-events',
1176
+ description: (0, load_description_js_1.loadDescription)('get-integration-events.md'),
1177
+ schema: {
1178
+ jobId: zod_1.z.string().describe('ID of the job to get events for'),
1179
+ integrationInstanceId: zod_1.z.string().describe('ID of the instance the job belongs to'),
1180
+ cursor: zod_1.z.string().optional().describe('Optional cursor for pagination'),
1181
+ size: zod_1.z
1182
+ .number()
1183
+ .min(1)
1184
+ .max(1000)
1185
+ .optional()
1186
+ .describe('Optional size limit for number of events to return (1-1000)'),
1187
+ },
1188
+ handler: async ({ jobId, integrationInstanceId, cursor, size }, client) => {
1189
+ try {
1190
+ const events = await client.getIntegrationEvents(jobId, integrationInstanceId, cursor, size);
1191
+ return {
1192
+ content: [
1193
+ {
1194
+ type: 'text',
1195
+ text: JSON.stringify({
1196
+ events: events.events.map((event) => ({
1197
+ id: event.id,
1198
+ name: event.name,
1199
+ description: event.description,
1200
+ createDate: event.createDate,
1201
+ jobId: event.jobId,
1202
+ level: event.level,
1203
+ eventCode: event.eventCode,
1204
+ })),
1205
+ pageInfo: events.pageInfo,
1206
+ }, null, 2),
1207
+ },
1208
+ ],
1209
+ };
1210
+ }
1211
+ catch (error) {
1212
+ return {
1213
+ content: [
1214
+ {
1215
+ type: 'text',
1216
+ text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}`,
1217
+ },
1218
+ ],
1219
+ isError: true,
1220
+ };
1221
+ }
1222
+ },
1096
1223
  });
1097
1224
  // Tool: List rule evaluations
1098
- this.server.tool('list-rule-evaluations', {
1099
- ruleId: z.string(),
1100
- beginTimestamp: z.number().optional(),
1101
- endTimestamp: z.number().optional(),
1102
- limit: z.number().min(1).max(1000).optional(),
1103
- tag: z.string().optional(),
1104
- }, async ({ ruleId, beginTimestamp, endTimestamp, limit, tag }) => {
1105
- try {
1106
- const evaluations = await this.client.getAllRuleEvaluations({
1107
- collectionType: 'RULE_EVALUATION',
1108
- collectionOwnerId: ruleId,
1109
- beginTimestamp: beginTimestamp || 0,
1110
- endTimestamp: endTimestamp || Date.now(),
1111
- limit,
1112
- tag,
1113
- });
1114
- return {
1115
- content: [
1116
- {
1117
- type: 'text',
1118
- text: JSON.stringify({
1119
- total: evaluations.length,
1120
- evaluations: evaluations.map((evaluation) => ({
1121
- accountId: evaluation.accountId,
1122
- collectionOwnerId: evaluation.collectionOwnerId,
1123
- collectionOwnerVersion: evaluation.collectionOwnerVersion,
1124
- collectionType: evaluation.collectionType,
1125
- outputs: evaluation.outputs,
1126
- rawDataDescriptors: evaluation.rawDataDescriptors,
1127
- tag: evaluation.tag,
1128
- timestamp: evaluation.timestamp,
1129
- })),
1130
- }, null, 2),
1131
- },
1132
- ],
1133
- };
1134
- }
1135
- catch (error) {
1136
- return {
1137
- content: [
1138
- {
1139
- type: 'text',
1140
- text: `Error listing rule evaluations: ${error instanceof Error ? error.message : 'Unknown error'}`,
1141
- },
1142
- ],
1143
- isError: true,
1144
- };
1145
- }
1225
+ this.registerTool({
1226
+ name: 'list-rule-evaluations',
1227
+ description: (0, load_description_js_1.loadDescription)('list-rule-evaluations.md'),
1228
+ schema: {
1229
+ ruleId: zod_1.z.string(),
1230
+ beginTimestamp: zod_1.z.number().optional(),
1231
+ endTimestamp: zod_1.z.number().optional(),
1232
+ limit: zod_1.z.number().min(1).max(1000).optional(),
1233
+ tag: zod_1.z.string().optional(),
1234
+ },
1235
+ handler: async ({ ruleId, beginTimestamp, endTimestamp, limit, tag }, client) => {
1236
+ try {
1237
+ const evaluations = await client.getAllRuleEvaluations({
1238
+ collectionType: 'RULE_EVALUATION',
1239
+ collectionOwnerId: ruleId,
1240
+ beginTimestamp: beginTimestamp || 0,
1241
+ endTimestamp: endTimestamp || Date.now(),
1242
+ limit,
1243
+ tag,
1244
+ });
1245
+ return {
1246
+ content: [
1247
+ {
1248
+ type: 'text',
1249
+ text: JSON.stringify({
1250
+ total: evaluations.length,
1251
+ evaluations: evaluations.map((evaluation) => ({
1252
+ accountId: evaluation.accountId,
1253
+ collectionOwnerId: evaluation.collectionOwnerId,
1254
+ collectionOwnerVersion: evaluation.collectionOwnerVersion,
1255
+ collectionType: evaluation.collectionType,
1256
+ outputs: evaluation.outputs,
1257
+ rawDataDescriptors: evaluation.rawDataDescriptors,
1258
+ tag: evaluation.tag,
1259
+ timestamp: evaluation.timestamp,
1260
+ })),
1261
+ }, null, 2),
1262
+ },
1263
+ ],
1264
+ };
1265
+ }
1266
+ catch (error) {
1267
+ return {
1268
+ content: [
1269
+ {
1270
+ type: 'text',
1271
+ text: `Error listing rule evaluations: ${error instanceof Error ? error.message : 'Unknown error'}`,
1272
+ },
1273
+ ],
1274
+ isError: true,
1275
+ };
1276
+ }
1277
+ },
1146
1278
  });
1147
1279
  // Tool: Get rule evaluation details
1148
- this.server.tool('get-rule-evaluation-details', {
1149
- ruleId: z.string(),
1150
- timestamp: z.number(),
1151
- }, async ({ ruleId, timestamp }) => {
1152
- try {
1153
- const details = await this.client.getRuleEvaluationDetails({
1154
- ruleInstanceId: ruleId,
1155
- timestamp,
1156
- });
1157
- return {
1158
- content: [
1159
- {
1160
- type: 'text',
1161
- text: JSON.stringify({
1162
- accountRuleId: details.accountRuleId,
1163
- startedOn: details.startedOn,
1164
- question: {
1165
- totalDuration: details.question.totalDuration,
1166
- queries: Array.isArray(details.question.queries)
1167
- ? details.question.queries.map((query) => ({
1168
- status: query.status,
1169
- queryEvaluationDetails: Array.isArray(query.queryEvaluationDetails)
1170
- ? query.queryEvaluationDetails.map((detail) => ({
1171
- name: detail.name,
1172
- duration: detail.duration,
1280
+ this.registerTool({
1281
+ name: 'get-rule-evaluation-details',
1282
+ description: (0, load_description_js_1.loadDescription)('get-rule-evaluation-details.md'),
1283
+ schema: {
1284
+ ruleId: zod_1.z.string(),
1285
+ timestamp: zod_1.z.number(),
1286
+ },
1287
+ handler: async ({ ruleId, timestamp }, client) => {
1288
+ try {
1289
+ const details = await client.getRuleEvaluationDetails({
1290
+ ruleInstanceId: ruleId,
1291
+ timestamp,
1292
+ });
1293
+ return {
1294
+ content: [
1295
+ {
1296
+ type: 'text',
1297
+ text: JSON.stringify({
1298
+ accountRuleId: details.accountRuleId,
1299
+ startedOn: details.startedOn,
1300
+ question: {
1301
+ totalDuration: details.question.totalDuration,
1302
+ queries: Array.isArray(details.question.queries)
1303
+ ? details.question.queries.map((query) => ({
1304
+ status: query.status,
1305
+ queryEvaluationDetails: Array.isArray(query.queryEvaluationDetails)
1306
+ ? query.queryEvaluationDetails.map((detail) => ({
1307
+ name: detail.name,
1308
+ duration: detail.duration,
1309
+ status: detail.status,
1310
+ error: detail.error,
1311
+ }))
1312
+ : [],
1313
+ }))
1314
+ : [],
1315
+ },
1316
+ conditions: Array.isArray(details.conditions)
1317
+ ? details.conditions.map((condition) => ({
1318
+ status: condition.status,
1319
+ condition: condition.condition,
1320
+ }))
1321
+ : [],
1322
+ actions: Array.isArray(details.actions)
1323
+ ? details.actions.map((action) => ({
1324
+ status: action.status,
1325
+ actionEvaluationDetails: Array.isArray(action.actionEvaluationDetails)
1326
+ ? action.actionEvaluationDetails.map((detail) => ({
1327
+ actionId: detail.actionId,
1328
+ action: detail.action,
1173
1329
  status: detail.status,
1174
- error: detail.error,
1330
+ duration: detail.duration,
1331
+ finishedOn: detail.finishedOn,
1332
+ logs: detail.logs,
1175
1333
  }))
1176
1334
  : [],
1177
1335
  }))
1178
1336
  : [],
1179
- },
1180
- conditions: Array.isArray(details.conditions)
1181
- ? details.conditions.map((condition) => ({
1182
- status: condition.status,
1183
- condition: condition.condition,
1184
- }))
1185
- : [],
1186
- actions: Array.isArray(details.actions)
1187
- ? details.actions.map((action) => ({
1188
- status: action.status,
1189
- actionEvaluationDetails: Array.isArray(action.actionEvaluationDetails)
1190
- ? action.actionEvaluationDetails.map((detail) => ({
1191
- actionId: detail.actionId,
1192
- action: detail.action,
1193
- status: detail.status,
1194
- duration: detail.duration,
1195
- finishedOn: detail.finishedOn,
1196
- logs: detail.logs,
1197
- }))
1198
- : [],
1199
- }))
1200
- : [],
1201
- ruleEvaluationOrigin: details.ruleEvaluationOrigin,
1202
- }, null, 2),
1203
- },
1204
- ],
1205
- };
1206
- }
1207
- catch (error) {
1208
- return {
1209
- content: [
1210
- {
1211
- type: 'text',
1212
- text: `Error getting rule evaluation details: ${error instanceof Error ? error.message : 'Unknown error'}`,
1213
- },
1214
- ],
1215
- isError: true,
1216
- };
1217
- }
1337
+ ruleEvaluationOrigin: details.ruleEvaluationOrigin,
1338
+ }, null, 2),
1339
+ },
1340
+ ],
1341
+ };
1342
+ }
1343
+ catch (error) {
1344
+ return {
1345
+ content: [
1346
+ {
1347
+ type: 'text',
1348
+ text: `Error getting rule evaluation details: ${error instanceof Error ? error.message : 'Unknown error'}`,
1349
+ },
1350
+ ],
1351
+ isError: true,
1352
+ };
1353
+ }
1354
+ },
1218
1355
  });
1219
1356
  // Tool: Get raw data download URL
1220
- this.server.tool('get-raw-data-download-url', {
1221
- rawDataKey: z.string(),
1222
- }, async ({ rawDataKey }) => {
1223
- try {
1224
- const downloadUrl = await this.client.getRawDataDownloadUrl(rawDataKey);
1225
- return {
1226
- content: [
1227
- {
1228
- type: 'text',
1229
- text: JSON.stringify({
1230
- rawDataKey,
1231
- downloadUrl,
1232
- }, null, 2),
1233
- },
1234
- ],
1235
- };
1236
- }
1237
- catch (error) {
1238
- return {
1239
- content: [
1240
- {
1241
- type: 'text',
1242
- text: `Error getting raw data download URL: ${error instanceof Error ? error.message : 'Unknown error'}`,
1243
- },
1244
- ],
1245
- isError: true,
1246
- };
1247
- }
1357
+ this.registerTool({
1358
+ name: 'get-raw-data-download-url',
1359
+ description: (0, load_description_js_1.loadDescription)('get-raw-data-download-url.md'),
1360
+ schema: {
1361
+ rawDataKey: zod_1.z.string(),
1362
+ },
1363
+ handler: async ({ rawDataKey }, client) => {
1364
+ try {
1365
+ const downloadUrl = await client.getRawDataDownloadUrl(rawDataKey);
1366
+ return {
1367
+ content: [
1368
+ {
1369
+ type: 'text',
1370
+ text: JSON.stringify({
1371
+ rawDataKey,
1372
+ downloadUrl,
1373
+ }, null, 2),
1374
+ },
1375
+ ],
1376
+ };
1377
+ }
1378
+ catch (error) {
1379
+ return {
1380
+ content: [
1381
+ {
1382
+ type: 'text',
1383
+ text: `Error getting raw data download URL: ${error instanceof Error ? error.message : 'Unknown error'}`,
1384
+ },
1385
+ ],
1386
+ isError: true,
1387
+ };
1388
+ }
1389
+ },
1248
1390
  });
1249
1391
  // Tool: Get rule evaluation query results
1250
- this.server.tool('get-rule-evaluation-query-results', {
1251
- rawDataKey: z.string(),
1252
- }, async ({ rawDataKey }) => {
1253
- try {
1254
- const results = await this.client.getRawDataResults(rawDataKey);
1255
- return {
1256
- content: [
1257
- {
1258
- type: 'text',
1259
- text: JSON.stringify(results, null, 2),
1260
- },
1261
- ],
1262
- };
1263
- }
1264
- catch (error) {
1265
- return {
1266
- content: [
1267
- {
1268
- type: 'text',
1269
- text: `Error getting rule evaluation query results: ${error instanceof Error ? error.message : 'Unknown error'}`,
1270
- },
1271
- ],
1272
- isError: true,
1273
- };
1274
- }
1392
+ this.registerTool({
1393
+ name: 'get-rule-evaluation-query-results',
1394
+ description: (0, load_description_js_1.loadDescription)('get-rule-evaluation-query-results.md'),
1395
+ schema: {
1396
+ rawDataKey: zod_1.z.string(),
1397
+ },
1398
+ handler: async ({ rawDataKey }, client) => {
1399
+ try {
1400
+ const results = await client.getRawDataResults(rawDataKey);
1401
+ return {
1402
+ content: [
1403
+ {
1404
+ type: 'text',
1405
+ text: JSON.stringify(results, null, 2),
1406
+ },
1407
+ ],
1408
+ };
1409
+ }
1410
+ catch (error) {
1411
+ return {
1412
+ content: [
1413
+ {
1414
+ type: 'text',
1415
+ text: `Error getting rule evaluation query results: ${error instanceof Error ? error.message : 'Unknown error'}`,
1416
+ },
1417
+ ],
1418
+ isError: true,
1419
+ };
1420
+ }
1421
+ },
1275
1422
  });
1276
1423
  // The server is not doing a great job of this, will uncomment when we have better support for this
1277
1424
  // Tool: Create J1QL from natural language
@@ -1317,194 +1464,215 @@ export class JupiterOneMcpServer {
1317
1464
  // }
1318
1465
  // );
1319
1466
  // Tool: Create dashboard widget
1320
- this.server.tool('create-dashboard-widget', loadDescription('create-dashboard-widget.md'), {
1321
- dashboardId: z.string().describe('ID of the dashboard to add the widget to'),
1322
- input: z.any().describe('Widget input object (CreateInsightsWidgetInput)'),
1323
- }, async ({ dashboardId, input }) => {
1324
- try {
1325
- let widgetInput = input;
1326
- if (typeof input === 'string') {
1327
- try {
1328
- widgetInput = JSON.parse(input);
1467
+ this.registerTool({
1468
+ name: 'create-dashboard-widget',
1469
+ description: (0, load_description_js_1.loadDescription)('create-dashboard-widget.md'),
1470
+ schema: {
1471
+ dashboardId: zod_1.z.string().describe('ID of the dashboard to add the widget to'),
1472
+ input: zod_1.z.any().describe('Widget input object (CreateInsightsWidgetInput)'),
1473
+ },
1474
+ handler: async ({ dashboardId, input }, client, validator) => {
1475
+ try {
1476
+ let widgetInput = input;
1477
+ if (typeof input === 'string') {
1478
+ try {
1479
+ widgetInput = JSON.parse(input);
1480
+ }
1481
+ catch (e) {
1482
+ throw new Error('Input must be a valid object or JSON string');
1483
+ }
1329
1484
  }
1330
- catch (e) {
1331
- throw new Error('Input must be a valid object or JSON string');
1485
+ // Validate queries before creating widget
1486
+ const validationResults = await this.validateWidgetQueries(widgetInput.config?.queries, validator);
1487
+ if (validationResults.length > 0) {
1488
+ return this.createValidationErrorResponse(validationResults);
1332
1489
  }
1490
+ const widget = await client.createDashboardWidget(dashboardId, widgetInput);
1491
+ // Get account info to construct the dashboard URL
1492
+ const accountInfo = await client.getAccountInfo();
1493
+ const dashboardUrl = client.dashboardService.constructDashboardUrl(dashboardId, accountInfo.subdomain);
1494
+ return {
1495
+ content: [
1496
+ {
1497
+ type: 'text',
1498
+ text: JSON.stringify({
1499
+ ...widget,
1500
+ dashboardUrl
1501
+ }, null, 2),
1502
+ },
1503
+ ],
1504
+ };
1333
1505
  }
1334
- // Validate queries before creating widget
1335
- const validationResults = await this.validateWidgetQueries(widgetInput.config?.queries);
1336
- if (validationResults.length > 0) {
1337
- return this.createValidationErrorResponse(validationResults);
1506
+ catch (error) {
1507
+ return {
1508
+ content: [
1509
+ {
1510
+ type: 'text',
1511
+ text: `Error creating dashboard widget: ${error instanceof Error ? error.message : 'Unknown error'}`,
1512
+ },
1513
+ ],
1514
+ isError: true,
1515
+ };
1338
1516
  }
1339
- const widget = await this.client.createDashboardWidget(dashboardId, widgetInput);
1340
- return {
1341
- content: [
1342
- {
1343
- type: 'text',
1344
- text: JSON.stringify(widget, null, 2),
1345
- },
1346
- ],
1347
- };
1348
- }
1349
- catch (error) {
1350
- return {
1351
- content: [
1352
- {
1353
- type: 'text',
1354
- text: `Error creating dashboard widget: ${error instanceof Error ? error.message : 'Unknown error'}`,
1355
- },
1356
- ],
1357
- isError: true,
1358
- };
1359
- }
1517
+ },
1360
1518
  });
1361
1519
  // Tool: Update dashboard
1362
- this.server.tool('update-dashboard', loadDescription('update-dashboard.md'), {
1363
- dashboardId: z.string().describe('ID of the dashboard to update'),
1364
- layouts: z
1365
- .object({
1366
- xs: z
1367
- .array(z.object({
1368
- w: z.number(),
1369
- h: z.number(),
1370
- x: z.number(),
1371
- y: z.number(),
1372
- i: z.string(),
1373
- moved: z.boolean(),
1374
- static: z.boolean(),
1375
- }))
1376
- .optional(),
1377
- sm: z
1378
- .array(z.object({
1379
- w: z.number(),
1380
- h: z.number(),
1381
- x: z.number(),
1382
- y: z.number(),
1383
- i: z.string(),
1384
- moved: z.boolean(),
1385
- static: z.boolean(),
1386
- }))
1387
- .optional(),
1388
- md: z
1389
- .array(z.object({
1390
- w: z.number(),
1391
- h: z.number(),
1392
- x: z.number(),
1393
- y: z.number(),
1394
- i: z.string(),
1395
- moved: z.boolean(),
1396
- static: z.boolean(),
1397
- }))
1398
- .optional(),
1399
- lg: z
1400
- .array(z.object({
1401
- w: z.number(),
1402
- h: z.number(),
1403
- x: z.number(),
1404
- y: z.number(),
1405
- i: z.string(),
1406
- moved: z.boolean(),
1407
- static: z.boolean(),
1408
- }))
1409
- .optional(),
1410
- xl: z
1411
- .array(z.object({
1412
- w: z.number(),
1413
- h: z.number(),
1414
- x: z.number(),
1415
- y: z.number(),
1416
- i: z.string(),
1417
- moved: z.boolean(),
1418
- static: z.boolean(),
1419
- }))
1420
- .optional(),
1421
- })
1422
- .describe('Layouts object for the dashboard'),
1423
- }, async ({ dashboardId, layouts }) => {
1424
- try {
1425
- const updated = await this.client.updateDashboard({ dashboardId, layouts });
1426
- return {
1427
- content: [
1428
- {
1429
- type: 'text',
1430
- text: JSON.stringify(updated, null, 2),
1431
- },
1432
- ],
1433
- };
1434
- }
1435
- catch (error) {
1436
- return {
1437
- content: [
1438
- {
1439
- type: 'text',
1440
- text: `Error updating dashboard: ${error instanceof Error ? error.message : 'Unknown error'}`,
1441
- },
1442
- ],
1443
- isError: true,
1444
- };
1445
- }
1520
+ this.registerTool({
1521
+ name: 'update-dashboard',
1522
+ description: (0, load_description_js_1.loadDescription)('update-dashboard.md'),
1523
+ schema: {
1524
+ dashboardId: zod_1.z.string().describe('ID of the dashboard to update'),
1525
+ layouts: zod_1.z
1526
+ .object({
1527
+ xs: zod_1.z
1528
+ .array(zod_1.z.object({
1529
+ w: zod_1.z.number(),
1530
+ h: zod_1.z.number(),
1531
+ x: zod_1.z.number(),
1532
+ y: zod_1.z.number(),
1533
+ i: zod_1.z.string(),
1534
+ moved: zod_1.z.boolean(),
1535
+ static: zod_1.z.boolean(),
1536
+ }))
1537
+ .optional(),
1538
+ sm: zod_1.z
1539
+ .array(zod_1.z.object({
1540
+ w: zod_1.z.number(),
1541
+ h: zod_1.z.number(),
1542
+ x: zod_1.z.number(),
1543
+ y: zod_1.z.number(),
1544
+ i: zod_1.z.string(),
1545
+ moved: zod_1.z.boolean(),
1546
+ static: zod_1.z.boolean(),
1547
+ }))
1548
+ .optional(),
1549
+ md: zod_1.z
1550
+ .array(zod_1.z.object({
1551
+ w: zod_1.z.number(),
1552
+ h: zod_1.z.number(),
1553
+ x: zod_1.z.number(),
1554
+ y: zod_1.z.number(),
1555
+ i: zod_1.z.string(),
1556
+ moved: zod_1.z.boolean(),
1557
+ static: zod_1.z.boolean(),
1558
+ }))
1559
+ .optional(),
1560
+ lg: zod_1.z
1561
+ .array(zod_1.z.object({
1562
+ w: zod_1.z.number(),
1563
+ h: zod_1.z.number(),
1564
+ x: zod_1.z.number(),
1565
+ y: zod_1.z.number(),
1566
+ i: zod_1.z.string(),
1567
+ moved: zod_1.z.boolean(),
1568
+ static: zod_1.z.boolean(),
1569
+ }))
1570
+ .optional(),
1571
+ xl: zod_1.z
1572
+ .array(zod_1.z.object({
1573
+ w: zod_1.z.number(),
1574
+ h: zod_1.z.number(),
1575
+ x: zod_1.z.number(),
1576
+ y: zod_1.z.number(),
1577
+ i: zod_1.z.string(),
1578
+ moved: zod_1.z.boolean(),
1579
+ static: zod_1.z.boolean(),
1580
+ }))
1581
+ .optional(),
1582
+ })
1583
+ .describe('Layouts object for the dashboard'),
1584
+ },
1585
+ handler: async ({ dashboardId, layouts }, client) => {
1586
+ try {
1587
+ const updated = await client.updateDashboard({ dashboardId, layouts });
1588
+ return {
1589
+ content: [
1590
+ {
1591
+ type: 'text',
1592
+ text: JSON.stringify(updated, null, 2),
1593
+ },
1594
+ ],
1595
+ };
1596
+ }
1597
+ catch (error) {
1598
+ return {
1599
+ content: [
1600
+ {
1601
+ type: 'text',
1602
+ text: `Error updating dashboard: ${error instanceof Error ? error.message : 'Unknown error'}`,
1603
+ },
1604
+ ],
1605
+ isError: true,
1606
+ };
1607
+ }
1608
+ },
1446
1609
  });
1447
1610
  // Tool: Execute J1QL query
1448
- this.server.tool('execute-j1ql-query', loadDescription('execute-j1ql-query.md'), {
1449
- query: z.string().describe('A J1QL query string that describes what data to return'),
1450
- variables: z
1451
- .record(z.any())
1452
- .optional()
1453
- .describe('A JSON map of values to be used as parameters for the query'),
1454
- cursor: z
1455
- .string()
1456
- .optional()
1457
- .describe('A token that can be exchanged to fetch the next page of information'),
1458
- includeDeleted: z
1459
- .boolean()
1460
- .optional()
1461
- .describe('Include recently deleted information in the results'),
1462
- deferredResponse: z
1463
- .enum(['DISABLED', 'FORCE'])
1464
- .optional()
1465
- .describe('Allows for a deferred response to be returned'),
1466
- flags: z.record(z.any()).optional().describe('Flags for query execution'),
1467
- scopeFilters: z
1468
- .array(z.record(z.any()))
1469
- .optional()
1470
- .describe('Array of filters that define the desired vertex'),
1471
- }, async ({ query, variables, cursor, includeDeleted, deferredResponse, flags, scopeFilters, }) => {
1472
- try {
1473
- // Build flags object
1474
- const queryFlags = { ...flags };
1475
- if (typeof includeDeleted === 'boolean')
1476
- queryFlags.includeDeleted = includeDeleted;
1477
- if (deferredResponse)
1478
- queryFlags.deferredResponse = deferredResponse;
1479
- const result = await this.client.executeJ1qlQuery({
1480
- query,
1481
- variables,
1482
- cursor,
1483
- scopeFilters,
1484
- flags: Object.keys(queryFlags).length > 0 ? queryFlags : undefined,
1485
- });
1486
- return {
1487
- content: [
1488
- {
1489
- type: 'text',
1490
- text: JSON.stringify(result, null, 2),
1491
- },
1492
- ],
1493
- };
1494
- }
1495
- catch (error) {
1496
- return this.createQueryErrorResponse(error, query);
1497
- }
1611
+ this.registerTool({
1612
+ name: 'execute-j1ql-query',
1613
+ description: (0, load_description_js_1.loadDescription)('execute-j1ql-query.md'),
1614
+ schema: {
1615
+ query: zod_1.z.string().describe('A J1QL query string that describes what data to return'),
1616
+ variables: zod_1.z
1617
+ .record(zod_1.z.any())
1618
+ .optional()
1619
+ .describe('A JSON map of values to be used as parameters for the query'),
1620
+ cursor: zod_1.z
1621
+ .string()
1622
+ .optional()
1623
+ .describe('A token that can be exchanged to fetch the next page of information'),
1624
+ includeDeleted: zod_1.z
1625
+ .boolean()
1626
+ .optional()
1627
+ .describe('Include recently deleted information in the results'),
1628
+ deferredResponse: zod_1.z
1629
+ .enum(['DISABLED', 'FORCE'])
1630
+ .optional()
1631
+ .describe('Allows for a deferred response to be returned'),
1632
+ flags: zod_1.z.record(zod_1.z.any()).optional().describe('Flags for query execution'),
1633
+ scopeFilters: zod_1.z
1634
+ .array(zod_1.z.record(zod_1.z.any()))
1635
+ .optional()
1636
+ .describe('Array of filters that define the desired vertex'),
1637
+ },
1638
+ handler: async ({ query, variables, cursor, includeDeleted, deferredResponse, flags, scopeFilters }, client, validator) => {
1639
+ try {
1640
+ // Build flags object
1641
+ const queryFlags = { ...flags };
1642
+ if (typeof includeDeleted === 'boolean')
1643
+ queryFlags.includeDeleted = includeDeleted;
1644
+ if (deferredResponse)
1645
+ queryFlags.deferredResponse = deferredResponse;
1646
+ const result = await client.executeJ1qlQuery({
1647
+ query,
1648
+ variables,
1649
+ cursor,
1650
+ scopeFilters,
1651
+ flags: Object.keys(queryFlags).length > 0 ? queryFlags : undefined,
1652
+ });
1653
+ return {
1654
+ content: [
1655
+ {
1656
+ type: 'text',
1657
+ text: JSON.stringify(result, null, 2),
1658
+ },
1659
+ ],
1660
+ };
1661
+ }
1662
+ catch (error) {
1663
+ return this.createQueryErrorResponse(error, query, validator);
1664
+ }
1665
+ },
1498
1666
  });
1499
1667
  }
1500
1668
  // Helper methods for validation
1501
- async validateQueries(queries) {
1669
+ async validateQueries(queries, validator) {
1502
1670
  if (!queries || !Array.isArray(queries))
1503
1671
  return [];
1504
1672
  const validationResults = [];
1505
1673
  for (const queryObj of queries) {
1506
1674
  if (queryObj.query) {
1507
- const validation = await this.validator.validateQuery(queryObj.query);
1675
+ const validation = await validator.validateQuery(queryObj.query);
1508
1676
  if (!validation.isValid) {
1509
1677
  validationResults.push({
1510
1678
  queryName: queryObj.name || 'Unnamed query',
@@ -1516,9 +1684,9 @@ export class JupiterOneMcpServer {
1516
1684
  }
1517
1685
  return validationResults;
1518
1686
  }
1519
- async validateWidgetQueries(queries) {
1687
+ async validateWidgetQueries(queries, validator) {
1520
1688
  // Use the same validation logic as rules - actually execute the queries
1521
- return this.validateQueries(queries);
1689
+ return this.validateQueries(queries, validator);
1522
1690
  }
1523
1691
  createValidationErrorResponse(validationResults) {
1524
1692
  return {
@@ -1533,8 +1701,8 @@ export class JupiterOneMcpServer {
1533
1701
  isError: true,
1534
1702
  };
1535
1703
  }
1536
- createQueryErrorResponse(error, query) {
1537
- const errorResult = this.validator.handleQueryError(error, query);
1704
+ createQueryErrorResponse(error, query, validator) {
1705
+ const errorResult = validator.handleQueryError(error, query);
1538
1706
  return {
1539
1707
  content: [
1540
1708
  {
@@ -1546,11 +1714,12 @@ export class JupiterOneMcpServer {
1546
1714
  };
1547
1715
  }
1548
1716
  async start() {
1549
- const transport = new StdioServerTransport();
1717
+ const transport = new stdio_js_1.StdioServerTransport();
1550
1718
  await this.server.connect(transport);
1551
1719
  }
1552
1720
  async stop() {
1553
1721
  // Cleanup if needed
1554
1722
  }
1555
1723
  }
1724
+ exports.JupiterOneMcpServer = JupiterOneMcpServer;
1556
1725
  //# sourceMappingURL=mcp-server.js.map