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