snow-flow 2.6.4 → 2.6.6
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/dist/mcp/servicenow-development-assistant-mcp.js +29 -4
- package/dist/queen/queen-memory.d.ts +12 -6
- package/dist/queen/queen-memory.js +264 -187
- package/dist/queen/types.d.ts +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +9 -0
- package/package.json +1 -1
- package/dist/mcp/example-refactored-server.d.ts +0 -18
- package/dist/mcp/example-refactored-server.js +0 -57
- package/dist/mcp/servicenow-automation-mcp-refactored.d.ts +0 -26
- package/dist/mcp/servicenow-automation-mcp-refactored.js +0 -632
- package/dist/mcp/servicenow-deployment-mcp-refactored.d.ts +0 -74
- package/dist/mcp/servicenow-deployment-mcp-refactored.js +0 -1044
- package/dist/mcp/servicenow-flow-composer-mcp-refactored.d.ts +0 -25
- package/dist/mcp/servicenow-flow-composer-mcp-refactored.js +0 -565
- package/dist/mcp/servicenow-graph-memory-mcp-refactored.d.ts +0 -32
- package/dist/mcp/servicenow-graph-memory-mcp-refactored.js +0 -642
- package/dist/mcp/servicenow-integration-mcp-refactored.d.ts +0 -24
- package/dist/mcp/servicenow-integration-mcp-refactored.js +0 -612
- package/dist/mcp/servicenow-intelligent-mcp-refactored.d.ts +0 -63
- package/dist/mcp/servicenow-intelligent-mcp-refactored.js +0 -782
- package/dist/mcp/servicenow-operations-mcp-refactored.d.ts +0 -63
- package/dist/mcp/servicenow-operations-mcp-refactored.js +0 -1770
- package/dist/mcp/servicenow-platform-development-mcp-refactored.d.ts +0 -25
- package/dist/mcp/servicenow-platform-development-mcp-refactored.js +0 -542
- package/dist/mcp/servicenow-reporting-analytics-mcp-refactored.d.ts +0 -26
- package/dist/mcp/servicenow-reporting-analytics-mcp-refactored.js +0 -648
- package/dist/mcp/servicenow-security-compliance-mcp-refactored.d.ts +0 -25
- package/dist/mcp/servicenow-security-compliance-mcp-refactored.js +0 -600
- package/dist/mcp/servicenow-update-set-mcp-refactored.d.ts +0 -31
- package/dist/mcp/servicenow-update-set-mcp-refactored.js +0 -662
|
@@ -1,662 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* ServiceNow Update Set Management MCP Server - REFACTORED
|
|
5
|
-
* Uses BaseMCPServer to eliminate code duplication
|
|
6
|
-
* Ensures all changes are tracked in Update Sets for safe deployment
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.ServiceNowUpdateSetMCP = void 0;
|
|
10
|
-
const base_mcp_server_js_1 = require("./base-mcp-server.js");
|
|
11
|
-
const fs_1 = require("fs");
|
|
12
|
-
const path_1 = require("path");
|
|
13
|
-
class ServiceNowUpdateSetMCP extends base_mcp_server_js_1.BaseMCPServer {
|
|
14
|
-
setupTools() {
|
|
15
|
-
// Tools are set up via getTools() method
|
|
16
|
-
}
|
|
17
|
-
constructor() {
|
|
18
|
-
super({
|
|
19
|
-
name: 'servicenow-update-set',
|
|
20
|
-
version: '2.0.0',
|
|
21
|
-
description: 'Update Set management server with BaseMCPServer pattern'
|
|
22
|
-
});
|
|
23
|
-
this.currentSession = null;
|
|
24
|
-
this.sessionsPath = (0, path_1.join)(process.cwd(), 'memory', 'update-set-sessions');
|
|
25
|
-
this.ensureSessionsDirectory();
|
|
26
|
-
this.loadActiveSession();
|
|
27
|
-
}
|
|
28
|
-
getTools() {
|
|
29
|
-
return [
|
|
30
|
-
{
|
|
31
|
-
name: 'snow_update_set_create',
|
|
32
|
-
description: 'Create a new Update Set for a user story or feature - ALWAYS use this before making changes',
|
|
33
|
-
inputSchema: {
|
|
34
|
-
type: 'object',
|
|
35
|
-
properties: {
|
|
36
|
-
name: { type: 'string', description: 'Update Set name (e.g., "STORY-123: Add incident widget")' },
|
|
37
|
-
description: { type: 'string', description: 'Detailed description of changes' },
|
|
38
|
-
user_story: { type: 'string', description: 'User story or ticket number' },
|
|
39
|
-
release_date: { type: 'string', description: 'Target release date (optional)' },
|
|
40
|
-
auto_switch: {
|
|
41
|
-
type: 'boolean',
|
|
42
|
-
default: true,
|
|
43
|
-
description: 'Automatically switch to the created Update Set (default: true)'
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
required: ['name', 'description']
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'snow_update_set_switch',
|
|
51
|
-
description: 'Switch to an existing Update Set - use this to continue work on a story',
|
|
52
|
-
inputSchema: {
|
|
53
|
-
type: 'object',
|
|
54
|
-
properties: {
|
|
55
|
-
update_set_id: { type: 'string', description: 'Update Set sys_id to switch to' }
|
|
56
|
-
},
|
|
57
|
-
required: ['update_set_id']
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'snow_update_set_current',
|
|
62
|
-
description: 'Get the current active Update Set session',
|
|
63
|
-
inputSchema: {
|
|
64
|
-
type: 'object',
|
|
65
|
-
properties: {}
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
name: 'snow_update_set_list',
|
|
70
|
-
description: 'List all Update Sets (in progress and recent)',
|
|
71
|
-
inputSchema: {
|
|
72
|
-
type: 'object',
|
|
73
|
-
properties: {
|
|
74
|
-
limit: { type: 'number', description: 'Maximum number of results (default: 10)' },
|
|
75
|
-
state: {
|
|
76
|
-
type: 'string',
|
|
77
|
-
enum: ['in_progress', 'complete', 'released'],
|
|
78
|
-
description: 'Filter by state'
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: 'snow_update_set_complete',
|
|
85
|
-
description: 'Mark Update Set as complete and ready for testing',
|
|
86
|
-
inputSchema: {
|
|
87
|
-
type: 'object',
|
|
88
|
-
properties: {
|
|
89
|
-
update_set_id: { type: 'string', description: 'Update Set sys_id to complete (uses current if not specified)' },
|
|
90
|
-
notes: { type: 'string', description: 'Completion notes or testing instructions' }
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: 'snow_update_set_add_artifact',
|
|
96
|
-
description: 'Track an artifact in the current Update Set session',
|
|
97
|
-
inputSchema: {
|
|
98
|
-
type: 'object',
|
|
99
|
-
properties: {
|
|
100
|
-
type: { type: 'string', description: 'Artifact type (widget, flow, script, etc.)' },
|
|
101
|
-
sys_id: { type: 'string', description: 'ServiceNow sys_id of the artifact' },
|
|
102
|
-
name: { type: 'string', description: 'Artifact name for tracking' }
|
|
103
|
-
},
|
|
104
|
-
required: ['type', 'sys_id', 'name']
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: 'snow_ensure_active_update_set',
|
|
109
|
-
description: 'Ensure there is an active Update Set session - creates one automatically if needed',
|
|
110
|
-
inputSchema: {
|
|
111
|
-
type: 'object',
|
|
112
|
-
properties: {
|
|
113
|
-
context: { type: 'string', description: 'Context for auto-created Update Set (e.g., "widget development", "flow creation")' },
|
|
114
|
-
auto_create: {
|
|
115
|
-
type: 'boolean',
|
|
116
|
-
default: true,
|
|
117
|
-
description: 'Automatically create Update Set if none exists (default: true)'
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
name: 'snow_update_set_preview',
|
|
124
|
-
description: 'Preview all changes in an Update Set',
|
|
125
|
-
inputSchema: {
|
|
126
|
-
type: 'object',
|
|
127
|
-
properties: {
|
|
128
|
-
update_set_id: { type: 'string', description: 'Update Set sys_id (uses current if not specified)' }
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
name: 'snow_update_set_export',
|
|
134
|
-
description: 'Export Update Set as XML for backup or migration',
|
|
135
|
-
inputSchema: {
|
|
136
|
-
type: 'object',
|
|
137
|
-
properties: {
|
|
138
|
-
update_set_id: { type: 'string', description: 'Update Set sys_id to export' },
|
|
139
|
-
output_path: { type: 'string', description: 'Path to save the XML file' }
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
];
|
|
144
|
-
}
|
|
145
|
-
async executeTool(name, args) {
|
|
146
|
-
switch (name) {
|
|
147
|
-
case 'snow_update_set_create':
|
|
148
|
-
return this.createUpdateSet(args);
|
|
149
|
-
case 'snow_update_set_switch':
|
|
150
|
-
return this.switchUpdateSet(args);
|
|
151
|
-
case 'snow_update_set_current':
|
|
152
|
-
return this.getCurrentUpdateSet();
|
|
153
|
-
case 'snow_update_set_list':
|
|
154
|
-
return this.listUpdateSets(args);
|
|
155
|
-
case 'snow_update_set_complete':
|
|
156
|
-
return this.completeUpdateSet(args);
|
|
157
|
-
case 'snow_update_set_add_artifact':
|
|
158
|
-
return this.addArtifactToSession(args);
|
|
159
|
-
case 'snow_ensure_active_update_set':
|
|
160
|
-
return this.ensureActiveUpdateSet(args);
|
|
161
|
-
case 'snow_update_set_preview':
|
|
162
|
-
return this.previewUpdateSet(args);
|
|
163
|
-
case 'snow_update_set_export':
|
|
164
|
-
return this.exportUpdateSet(args);
|
|
165
|
-
default:
|
|
166
|
-
return {
|
|
167
|
-
success: false,
|
|
168
|
-
error: `Unknown tool: ${name}`
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
async createUpdateSet(args) {
|
|
173
|
-
const startTime = Date.now();
|
|
174
|
-
try {
|
|
175
|
-
const { name, description, user_story, release_date, auto_switch = true } = args;
|
|
176
|
-
// Create Update Set in ServiceNow
|
|
177
|
-
const updateSetData = {
|
|
178
|
-
name,
|
|
179
|
-
description,
|
|
180
|
-
user_story,
|
|
181
|
-
release_date: release_date || '',
|
|
182
|
-
state: 'in_progress',
|
|
183
|
-
application: 'global'
|
|
184
|
-
};
|
|
185
|
-
const response = await this.client.makeRequest({
|
|
186
|
-
method: 'POST',
|
|
187
|
-
url: '/api/now/table/sys_update_set',
|
|
188
|
-
data: updateSetData
|
|
189
|
-
});
|
|
190
|
-
// Validate response structure
|
|
191
|
-
if (!response || !response.result) {
|
|
192
|
-
throw new Error(`Invalid API response: ${JSON.stringify(response)}`);
|
|
193
|
-
}
|
|
194
|
-
const updateSet = response.result;
|
|
195
|
-
// Create session
|
|
196
|
-
const session = {
|
|
197
|
-
update_set_id: updateSet.sys_id,
|
|
198
|
-
name: updateSet.name,
|
|
199
|
-
description: updateSet.description,
|
|
200
|
-
user_story: updateSet.user_story,
|
|
201
|
-
created_at: new Date().toISOString(),
|
|
202
|
-
state: 'in_progress',
|
|
203
|
-
artifacts: [],
|
|
204
|
-
auto_switched: auto_switch,
|
|
205
|
-
active_session: auto_switch
|
|
206
|
-
};
|
|
207
|
-
// Save session
|
|
208
|
-
await this.saveSession(session);
|
|
209
|
-
// Switch to new Update Set if requested
|
|
210
|
-
if (auto_switch) {
|
|
211
|
-
await this.switchToUpdateSet(updateSet.sys_id);
|
|
212
|
-
this.currentSession = session;
|
|
213
|
-
}
|
|
214
|
-
this.logger.info(`Created Update Set: ${name} (${updateSet.sys_id})`);
|
|
215
|
-
return {
|
|
216
|
-
success: true,
|
|
217
|
-
result: {
|
|
218
|
-
update_set_id: updateSet.sys_id,
|
|
219
|
-
name: updateSet.name,
|
|
220
|
-
switched: auto_switch,
|
|
221
|
-
session_created: true
|
|
222
|
-
},
|
|
223
|
-
executionTime: Date.now() - startTime
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
catch (error) {
|
|
227
|
-
this.logger.error('Failed to create Update Set', error);
|
|
228
|
-
return {
|
|
229
|
-
success: false,
|
|
230
|
-
error: error instanceof Error ? error.message : 'Failed to create Update Set',
|
|
231
|
-
retryable: false, // Simplified error handling
|
|
232
|
-
executionTime: Date.now() - startTime
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
async switchUpdateSet(args) {
|
|
237
|
-
const startTime = Date.now();
|
|
238
|
-
try {
|
|
239
|
-
const { update_set_id } = args;
|
|
240
|
-
// Switch in ServiceNow
|
|
241
|
-
await this.switchToUpdateSet(update_set_id);
|
|
242
|
-
// Load or create session for this Update Set
|
|
243
|
-
let session = await this.loadSessionById(update_set_id);
|
|
244
|
-
if (!session) {
|
|
245
|
-
// Fetch Update Set details from ServiceNow
|
|
246
|
-
const response = await this.client.makeRequest({
|
|
247
|
-
method: 'GET',
|
|
248
|
-
url: `/api/now/table/sys_update_set/${update_set_id}`
|
|
249
|
-
});
|
|
250
|
-
const updateSet = response.result;
|
|
251
|
-
// Create new session
|
|
252
|
-
session = {
|
|
253
|
-
update_set_id: updateSet.sys_id,
|
|
254
|
-
name: updateSet.name,
|
|
255
|
-
description: updateSet.description,
|
|
256
|
-
user_story: updateSet.user_story,
|
|
257
|
-
created_at: updateSet.sys_created_on,
|
|
258
|
-
state: updateSet.state,
|
|
259
|
-
artifacts: [],
|
|
260
|
-
active_session: true
|
|
261
|
-
};
|
|
262
|
-
await this.saveSession(session);
|
|
263
|
-
}
|
|
264
|
-
// Mark as current session
|
|
265
|
-
this.currentSession = session;
|
|
266
|
-
this.currentSession.active_session = true;
|
|
267
|
-
await this.saveSession(this.currentSession);
|
|
268
|
-
return {
|
|
269
|
-
success: true,
|
|
270
|
-
result: {
|
|
271
|
-
update_set_id: session.update_set_id,
|
|
272
|
-
name: session.name,
|
|
273
|
-
artifacts_count: session.artifacts.length
|
|
274
|
-
},
|
|
275
|
-
executionTime: Date.now() - startTime
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
catch (error) {
|
|
279
|
-
this.logger.error('Failed to switch Update Set', error);
|
|
280
|
-
return {
|
|
281
|
-
success: false,
|
|
282
|
-
error: error instanceof Error ? error.message : 'Failed to switch Update Set',
|
|
283
|
-
retryable: false, // Simplified error handling
|
|
284
|
-
executionTime: Date.now() - startTime
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
async getCurrentUpdateSet() {
|
|
289
|
-
const startTime = Date.now();
|
|
290
|
-
try {
|
|
291
|
-
if (!this.currentSession) {
|
|
292
|
-
// Try to get from ServiceNow
|
|
293
|
-
const response = await this.client.makeRequest({
|
|
294
|
-
method: 'GET',
|
|
295
|
-
url: '/api/now/table/sys_update_set',
|
|
296
|
-
params: {
|
|
297
|
-
sysparm_query: 'state=in_progress^sys_created_byDYNAMIC90d1921e5f510100a9ad2572f2b477fe',
|
|
298
|
-
sysparm_limit: 1,
|
|
299
|
-
sysparm_fields: 'sys_id,name,description,state'
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
if (response.result && response.result.length > 0) {
|
|
303
|
-
const updateSet = response.result[0];
|
|
304
|
-
return {
|
|
305
|
-
success: true,
|
|
306
|
-
result: {
|
|
307
|
-
update_set_id: updateSet.sys_id,
|
|
308
|
-
name: updateSet.name,
|
|
309
|
-
description: updateSet.description,
|
|
310
|
-
state: updateSet.state,
|
|
311
|
-
session_active: false
|
|
312
|
-
},
|
|
313
|
-
executionTime: Date.now() - startTime
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
return {
|
|
317
|
-
success: true,
|
|
318
|
-
result: {
|
|
319
|
-
message: 'No active Update Set session found',
|
|
320
|
-
recommendation: 'Use snow_update_set_create to create a new Update Set'
|
|
321
|
-
},
|
|
322
|
-
executionTime: Date.now() - startTime
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
return {
|
|
326
|
-
success: true,
|
|
327
|
-
result: {
|
|
328
|
-
update_set_id: this.currentSession.update_set_id,
|
|
329
|
-
name: this.currentSession.name,
|
|
330
|
-
description: this.currentSession.description,
|
|
331
|
-
state: this.currentSession.state,
|
|
332
|
-
artifacts_count: this.currentSession.artifacts.length,
|
|
333
|
-
artifacts: this.currentSession.artifacts,
|
|
334
|
-
session_active: true
|
|
335
|
-
},
|
|
336
|
-
executionTime: Date.now() - startTime
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
catch (error) {
|
|
340
|
-
this.logger.error('Failed to get current Update Set', error);
|
|
341
|
-
return {
|
|
342
|
-
success: false,
|
|
343
|
-
error: error instanceof Error ? error.message : 'Failed to get current Update Set',
|
|
344
|
-
retryable: false, // Simplified error handling
|
|
345
|
-
executionTime: Date.now() - startTime
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
async listUpdateSets(args) {
|
|
350
|
-
const startTime = Date.now();
|
|
351
|
-
try {
|
|
352
|
-
const { limit = 10, state } = args;
|
|
353
|
-
let query = 'ORDERBYDESCsys_created_on';
|
|
354
|
-
if (state) {
|
|
355
|
-
query = `state=${state}^${query}`;
|
|
356
|
-
}
|
|
357
|
-
const response = await this.client.makeRequest({
|
|
358
|
-
method: 'GET',
|
|
359
|
-
url: '/api/now/table/sys_update_set',
|
|
360
|
-
params: {
|
|
361
|
-
sysparm_query: query,
|
|
362
|
-
sysparm_limit: limit,
|
|
363
|
-
sysparm_fields: 'sys_id,name,description,state,sys_created_on,sys_created_by'
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
return {
|
|
367
|
-
success: true,
|
|
368
|
-
result: {
|
|
369
|
-
update_sets: response.result,
|
|
370
|
-
count: response.result.length,
|
|
371
|
-
current_session: this.currentSession?.update_set_id
|
|
372
|
-
},
|
|
373
|
-
executionTime: Date.now() - startTime
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
catch (error) {
|
|
377
|
-
this.logger.error('Failed to list Update Sets', error);
|
|
378
|
-
return {
|
|
379
|
-
success: false,
|
|
380
|
-
error: error instanceof Error ? error.message : 'Failed to list Update Sets',
|
|
381
|
-
retryable: false, // Simplified error handling
|
|
382
|
-
executionTime: Date.now() - startTime
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
async completeUpdateSet(args) {
|
|
387
|
-
const startTime = Date.now();
|
|
388
|
-
try {
|
|
389
|
-
const { update_set_id, notes } = args;
|
|
390
|
-
const targetId = update_set_id || this.currentSession?.update_set_id;
|
|
391
|
-
if (!targetId) {
|
|
392
|
-
throw new Error('No Update Set specified and no active session');
|
|
393
|
-
}
|
|
394
|
-
// Update state in ServiceNow
|
|
395
|
-
const updateData = {
|
|
396
|
-
state: 'complete',
|
|
397
|
-
description: notes ? `${this.currentSession?.description}\n\nCompletion Notes: ${notes}` : undefined
|
|
398
|
-
};
|
|
399
|
-
await this.makeAuthenticatedRequest({
|
|
400
|
-
method: 'PATCH',
|
|
401
|
-
url: `/api/now/table/sys_update_set/${targetId}`,
|
|
402
|
-
data: updateData
|
|
403
|
-
});
|
|
404
|
-
// Update session if it's the current one
|
|
405
|
-
if (this.currentSession && this.currentSession.update_set_id === targetId) {
|
|
406
|
-
this.currentSession.state = 'complete';
|
|
407
|
-
await this.saveSession(this.currentSession);
|
|
408
|
-
this.currentSession = null; // Clear current session
|
|
409
|
-
}
|
|
410
|
-
return {
|
|
411
|
-
success: true,
|
|
412
|
-
result: {
|
|
413
|
-
update_set_id: targetId,
|
|
414
|
-
state: 'complete',
|
|
415
|
-
notes: notes || 'Update Set completed'
|
|
416
|
-
},
|
|
417
|
-
executionTime: Date.now() - startTime
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
catch (error) {
|
|
421
|
-
this.logger.error('Failed to complete Update Set', error);
|
|
422
|
-
return {
|
|
423
|
-
success: false,
|
|
424
|
-
error: error instanceof Error ? error.message : 'Failed to complete Update Set',
|
|
425
|
-
retryable: false, // Simplified error handling
|
|
426
|
-
executionTime: Date.now() - startTime
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
async addArtifactToSession(args) {
|
|
431
|
-
const startTime = Date.now();
|
|
432
|
-
try {
|
|
433
|
-
const { type, sys_id, name } = args;
|
|
434
|
-
if (!this.currentSession) {
|
|
435
|
-
throw new Error('No active Update Set session. Create or switch to an Update Set first.');
|
|
436
|
-
}
|
|
437
|
-
// Add artifact to session
|
|
438
|
-
const artifact = {
|
|
439
|
-
type,
|
|
440
|
-
sys_id,
|
|
441
|
-
name,
|
|
442
|
-
created_at: new Date().toISOString()
|
|
443
|
-
};
|
|
444
|
-
this.currentSession.artifacts.push(artifact);
|
|
445
|
-
await this.saveSession(this.currentSession);
|
|
446
|
-
this.logger.info(`Tracked artifact: ${type} - ${name} (${sys_id})`);
|
|
447
|
-
return {
|
|
448
|
-
success: true,
|
|
449
|
-
result: {
|
|
450
|
-
artifact_tracked: true,
|
|
451
|
-
update_set_id: this.currentSession.update_set_id,
|
|
452
|
-
total_artifacts: this.currentSession.artifacts.length
|
|
453
|
-
},
|
|
454
|
-
executionTime: Date.now() - startTime
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
catch (error) {
|
|
458
|
-
this.logger.error('Failed to track artifact', error);
|
|
459
|
-
return {
|
|
460
|
-
success: false,
|
|
461
|
-
error: error instanceof Error ? error.message : 'Failed to track artifact',
|
|
462
|
-
retryable: false,
|
|
463
|
-
executionTime: Date.now() - startTime
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
async ensureActiveUpdateSet(args) {
|
|
468
|
-
const startTime = Date.now();
|
|
469
|
-
try {
|
|
470
|
-
const { context = 'general development', auto_create = true } = args;
|
|
471
|
-
// Check if we have an active session
|
|
472
|
-
if (this.currentSession && this.currentSession.state === 'in_progress') {
|
|
473
|
-
return {
|
|
474
|
-
success: true,
|
|
475
|
-
result: {
|
|
476
|
-
update_set_id: this.currentSession.update_set_id,
|
|
477
|
-
name: this.currentSession.name,
|
|
478
|
-
already_active: true
|
|
479
|
-
},
|
|
480
|
-
executionTime: Date.now() - startTime
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
// Check ServiceNow for active Update Sets
|
|
484
|
-
const response = await this.client.makeRequest({
|
|
485
|
-
method: 'GET',
|
|
486
|
-
url: '/api/now/table/sys_update_set',
|
|
487
|
-
params: {
|
|
488
|
-
sysparm_query: 'state=in_progress',
|
|
489
|
-
sysparm_limit: 1,
|
|
490
|
-
sysparm_fields: 'sys_id,name,description'
|
|
491
|
-
}
|
|
492
|
-
});
|
|
493
|
-
if (response.result && response.result.length > 0) {
|
|
494
|
-
// Switch to existing Update Set
|
|
495
|
-
const updateSet = response.result[0];
|
|
496
|
-
return this.switchUpdateSet({ update_set_id: updateSet.sys_id });
|
|
497
|
-
}
|
|
498
|
-
// Auto-create if enabled
|
|
499
|
-
if (auto_create) {
|
|
500
|
-
const timestamp = new Date().toISOString().split('T')[0];
|
|
501
|
-
return this.createUpdateSet({
|
|
502
|
-
name: `Auto-created: ${context} - ${timestamp}`,
|
|
503
|
-
description: `Automatically created Update Set for ${context}`,
|
|
504
|
-
auto_switch: true
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
return {
|
|
508
|
-
success: false,
|
|
509
|
-
error: 'No active Update Set and auto-create disabled',
|
|
510
|
-
result: {
|
|
511
|
-
recommendation: 'Create an Update Set with snow_update_set_create'
|
|
512
|
-
},
|
|
513
|
-
executionTime: Date.now() - startTime
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
catch (error) {
|
|
517
|
-
this.logger.error('Failed to ensure active Update Set', error);
|
|
518
|
-
return {
|
|
519
|
-
success: false,
|
|
520
|
-
error: error instanceof Error ? error.message : 'Failed to ensure active Update Set',
|
|
521
|
-
retryable: false, // Simplified error handling
|
|
522
|
-
executionTime: Date.now() - startTime
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
async previewUpdateSet(args) {
|
|
527
|
-
const startTime = Date.now();
|
|
528
|
-
try {
|
|
529
|
-
const update_set_id = args.update_set_id || this.currentSession?.update_set_id;
|
|
530
|
-
if (!update_set_id) {
|
|
531
|
-
throw new Error('No Update Set specified and no active session');
|
|
532
|
-
}
|
|
533
|
-
// Get Update Set details
|
|
534
|
-
const response = await this.client.makeRequest({
|
|
535
|
-
method: 'GET',
|
|
536
|
-
url: `/api/now/table/sys_update_xml`,
|
|
537
|
-
params: {
|
|
538
|
-
sysparm_query: `update_set=${update_set_id}`,
|
|
539
|
-
sysparm_fields: 'sys_id,name,type,target_name,action,sys_created_on'
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
return {
|
|
543
|
-
success: true,
|
|
544
|
-
result: {
|
|
545
|
-
update_set_id,
|
|
546
|
-
changes_count: response.result.length,
|
|
547
|
-
changes: response.result
|
|
548
|
-
},
|
|
549
|
-
executionTime: Date.now() - startTime
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
catch (error) {
|
|
553
|
-
this.logger.error('Failed to preview Update Set', error);
|
|
554
|
-
return {
|
|
555
|
-
success: false,
|
|
556
|
-
error: error instanceof Error ? error.message : 'Failed to preview Update Set',
|
|
557
|
-
retryable: false, // Simplified error handling
|
|
558
|
-
executionTime: Date.now() - startTime
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
async exportUpdateSet(args) {
|
|
563
|
-
const startTime = Date.now();
|
|
564
|
-
try {
|
|
565
|
-
const { update_set_id, output_path } = args;
|
|
566
|
-
if (!update_set_id) {
|
|
567
|
-
throw new Error('Update Set ID is required for export');
|
|
568
|
-
}
|
|
569
|
-
// Export Update Set as XML
|
|
570
|
-
const response = await this.client.makeRequest({
|
|
571
|
-
method: 'GET',
|
|
572
|
-
url: `/api/now/table/sys_update_set/${update_set_id}/export`,
|
|
573
|
-
responseType: 'text'
|
|
574
|
-
});
|
|
575
|
-
// Save to file if path provided
|
|
576
|
-
if (output_path) {
|
|
577
|
-
await fs_1.promises.writeFile(output_path, response.result);
|
|
578
|
-
}
|
|
579
|
-
return {
|
|
580
|
-
success: true,
|
|
581
|
-
result: {
|
|
582
|
-
update_set_id,
|
|
583
|
-
exported: true,
|
|
584
|
-
output_path: output_path || 'returned in response',
|
|
585
|
-
size: response.result.length
|
|
586
|
-
},
|
|
587
|
-
executionTime: Date.now() - startTime
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
|
-
catch (error) {
|
|
591
|
-
this.logger.error('Failed to export Update Set', error);
|
|
592
|
-
return {
|
|
593
|
-
success: false,
|
|
594
|
-
error: error instanceof Error ? error.message : 'Failed to export Update Set',
|
|
595
|
-
retryable: false, // Simplified error handling
|
|
596
|
-
executionTime: Date.now() - startTime
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
// Helper methods
|
|
601
|
-
async switchToUpdateSet(updateSetId) {
|
|
602
|
-
// Switch Update Set context in ServiceNow
|
|
603
|
-
await this.client.makeRequest({
|
|
604
|
-
method: 'PUT',
|
|
605
|
-
url: `/api/now/table/sys_user_preference`,
|
|
606
|
-
data: {
|
|
607
|
-
name: 'sys_update_set',
|
|
608
|
-
value: updateSetId,
|
|
609
|
-
user: 'current'
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
async ensureSessionsDirectory() {
|
|
614
|
-
try {
|
|
615
|
-
await fs_1.promises.mkdir(this.sessionsPath, { recursive: true });
|
|
616
|
-
}
|
|
617
|
-
catch (error) {
|
|
618
|
-
this.logger.error('Failed to create sessions directory', error);
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
async saveSession(session) {
|
|
622
|
-
const sessionFile = (0, path_1.join)(this.sessionsPath, `${session.update_set_id}.json`);
|
|
623
|
-
await fs_1.promises.writeFile(sessionFile, JSON.stringify(session, null, 2));
|
|
624
|
-
}
|
|
625
|
-
async loadSessionById(updateSetId) {
|
|
626
|
-
try {
|
|
627
|
-
const sessionFile = (0, path_1.join)(this.sessionsPath, `${updateSetId}.json`);
|
|
628
|
-
const content = await fs_1.promises.readFile(sessionFile, 'utf-8');
|
|
629
|
-
return JSON.parse(content);
|
|
630
|
-
}
|
|
631
|
-
catch (error) {
|
|
632
|
-
return null;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
async loadActiveSession() {
|
|
636
|
-
try {
|
|
637
|
-
const files = await fs_1.promises.readdir(this.sessionsPath);
|
|
638
|
-
for (const file of files) {
|
|
639
|
-
if (file.endsWith('.json')) {
|
|
640
|
-
const sessionFile = (0, path_1.join)(this.sessionsPath, file);
|
|
641
|
-
const content = await fs_1.promises.readFile(sessionFile, 'utf-8');
|
|
642
|
-
const session = JSON.parse(content);
|
|
643
|
-
if (session.active_session && session.state === 'in_progress') {
|
|
644
|
-
this.currentSession = session;
|
|
645
|
-
this.logger.info(`Loaded active Update Set session: ${session.name}`);
|
|
646
|
-
break;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
catch (error) {
|
|
652
|
-
this.logger.warn('No active Update Set session found');
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
exports.ServiceNowUpdateSetMCP = ServiceNowUpdateSetMCP;
|
|
657
|
-
// Create and run the server
|
|
658
|
-
if (require.main === module) {
|
|
659
|
-
const server = new ServiceNowUpdateSetMCP();
|
|
660
|
-
server.start().catch(console.error);
|
|
661
|
-
}
|
|
662
|
-
//# sourceMappingURL=servicenow-update-set-mcp-refactored.js.map
|