snow-flow 3.3.0 → 3.3.2

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.
@@ -0,0 +1,1112 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * ServiceNow CMDB, Event Management, HR, CSM & DevOps MCP Server - ENHANCED VERSION
5
+ * With logging, token tracking, and progress indicators
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
9
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
10
+ const enhanced_base_mcp_server_js_1 = require("./shared/enhanced-base-mcp-server.js");
11
+ const mcp_config_manager_js_1 = require("../utils/mcp-config-manager.js");
12
+ class ServiceNowCMDBEventHRCSMDevOpsMCPEnhanced extends enhanced_base_mcp_server_js_1.EnhancedBaseMCPServer {
13
+ constructor() {
14
+ super('servicenow-cmdb-event-hr-csm-devops-enhanced', '2.0.0');
15
+ this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
16
+ this.setupHandlers();
17
+ }
18
+ setupHandlers() {
19
+ this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
20
+ tools: [
21
+ // CMDB & Discovery Tools
22
+ {
23
+ name: 'snow_create_cmdb_ci',
24
+ description: 'Creates configuration item in CMDB using cmdb_ci_* tables.',
25
+ inputSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ ci_class: { type: 'string', description: 'CI class (e.g., cmdb_ci_server, cmdb_ci_appl)' },
29
+ name: { type: 'string', description: 'CI name' },
30
+ asset_tag: { type: 'string', description: 'Asset tag' },
31
+ serial_number: { type: 'string', description: 'Serial number' },
32
+ model_id: { type: 'string', description: 'Model sys_id' },
33
+ location: { type: 'string', description: 'Location sys_id' },
34
+ operational_status: { type: 'string', description: 'Status: operational, non-operational' },
35
+ attributes: { type: 'object', description: 'Additional CI attributes' }
36
+ },
37
+ required: ['ci_class', 'name']
38
+ }
39
+ },
40
+ {
41
+ name: 'snow_create_ci_relationship',
42
+ description: 'Creates CI relationship using cmdb_rel_ci table.',
43
+ inputSchema: {
44
+ type: 'object',
45
+ properties: {
46
+ parent: { type: 'string', description: 'Parent CI sys_id' },
47
+ child: { type: 'string', description: 'Child CI sys_id' },
48
+ type: { type: 'string', description: 'Relationship type sys_id' },
49
+ description: { type: 'string', description: 'Relationship description' }
50
+ },
51
+ required: ['parent', 'child', 'type']
52
+ }
53
+ },
54
+ {
55
+ name: 'snow_discover_ci_dependencies',
56
+ description: 'Discovers CI dependencies from cmdb_rel_ci table.',
57
+ inputSchema: {
58
+ type: 'object',
59
+ properties: {
60
+ ci_sys_id: { type: 'string', description: 'CI sys_id' },
61
+ depth: { type: 'number', default: 2, description: 'Dependency depth' },
62
+ direction: { type: 'string', description: 'upstream, downstream, both' }
63
+ },
64
+ required: ['ci_sys_id']
65
+ }
66
+ },
67
+ {
68
+ name: 'snow_run_discovery',
69
+ description: 'Runs discovery schedule using discovery_status table.',
70
+ inputSchema: {
71
+ type: 'object',
72
+ properties: {
73
+ schedule_sys_id: { type: 'string', description: 'Discovery schedule sys_id' },
74
+ ip_range: { type: 'string', description: 'IP range to discover' },
75
+ mid_server: { type: 'string', description: 'MID server sys_id' }
76
+ },
77
+ required: ['schedule_sys_id']
78
+ }
79
+ },
80
+ {
81
+ name: 'snow_get_discovery_status',
82
+ description: 'Gets discovery status from discovery_status table.',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ schedule_sys_id: { type: 'string', description: 'Discovery schedule sys_id' },
87
+ limit: { type: 'number', default: 10 }
88
+ }
89
+ }
90
+ },
91
+ {
92
+ name: 'snow_import_cmdb_data',
93
+ description: 'Imports CMDB data using sys_import_set table.',
94
+ inputSchema: {
95
+ type: 'object',
96
+ properties: {
97
+ table_name: { type: 'string', description: 'Target table' },
98
+ data: { type: 'array', items: { type: 'object' }, description: 'Data to import' },
99
+ transform_map: { type: 'string', description: 'Transform map sys_id' }
100
+ },
101
+ required: ['table_name', 'data']
102
+ }
103
+ },
104
+ // Event Management Tools
105
+ {
106
+ name: 'snow_create_event',
107
+ description: 'Creates event using em_event table.',
108
+ inputSchema: {
109
+ type: 'object',
110
+ properties: {
111
+ source: { type: 'string', description: 'Event source' },
112
+ node: { type: 'string', description: 'Node/CI' },
113
+ type: { type: 'string', description: 'Event type' },
114
+ severity: { type: 'string', description: '1-critical to 5-info' },
115
+ description: { type: 'string', description: 'Event description' },
116
+ message_key: { type: 'string', description: 'Unique message key' },
117
+ metric_name: { type: 'string', description: 'Metric name' },
118
+ resource: { type: 'string', description: 'Resource identifier' }
119
+ },
120
+ required: ['source', 'node', 'type', 'severity']
121
+ }
122
+ },
123
+ {
124
+ name: 'snow_create_alert_rule',
125
+ description: 'Creates alert rule using em_alert_rule table.',
126
+ inputSchema: {
127
+ type: 'object',
128
+ properties: {
129
+ name: { type: 'string', description: 'Rule name' },
130
+ condition: { type: 'string', description: 'Alert condition' },
131
+ threshold: { type: 'number', description: 'Threshold value' },
132
+ action: { type: 'string', description: 'Action to take' },
133
+ active: { type: 'boolean', default: true }
134
+ },
135
+ required: ['name', 'condition']
136
+ }
137
+ },
138
+ {
139
+ name: 'snow_correlate_alerts',
140
+ description: 'Correlates alerts using em_alert table.',
141
+ inputSchema: {
142
+ type: 'object',
143
+ properties: {
144
+ alerts: { type: 'array', items: { type: 'string' }, description: 'Alert sys_ids' },
145
+ correlation_rule: { type: 'string', description: 'Rule sys_id' },
146
+ create_incident: { type: 'boolean', default: false }
147
+ },
148
+ required: ['alerts']
149
+ }
150
+ },
151
+ {
152
+ name: 'snow_get_event_metrics',
153
+ description: 'Gets event metrics from em_event table.',
154
+ inputSchema: {
155
+ type: 'object',
156
+ properties: {
157
+ source: { type: 'string', description: 'Filter by source' },
158
+ node: { type: 'string', description: 'Filter by node' },
159
+ time_range: { type: 'string', description: 'Time range' },
160
+ group_by: { type: 'string', description: 'Group by field' }
161
+ }
162
+ }
163
+ },
164
+ // HR Service Delivery Tools
165
+ {
166
+ name: 'snow_create_hr_case',
167
+ description: 'Creates HR case using sn_hr_core_case table.',
168
+ inputSchema: {
169
+ type: 'object',
170
+ properties: {
171
+ subject_person: { type: 'string', description: 'Employee sys_id' },
172
+ short_description: { type: 'string', description: 'Case description' },
173
+ category: { type: 'string', description: 'HR category' },
174
+ subcategory: { type: 'string', description: 'HR subcategory' },
175
+ priority: { type: 'string', description: 'Priority level' },
176
+ confidential: { type: 'boolean', default: false },
177
+ hr_service: { type: 'string', description: 'HR service sys_id' }
178
+ },
179
+ required: ['subject_person', 'short_description']
180
+ }
181
+ },
182
+ {
183
+ name: 'snow_manage_onboarding',
184
+ description: 'Manages employee onboarding using sn_hr_core_task table.',
185
+ inputSchema: {
186
+ type: 'object',
187
+ properties: {
188
+ employee_sys_id: { type: 'string', description: 'New employee sys_id' },
189
+ start_date: { type: 'string', description: 'Start date' },
190
+ department: { type: 'string', description: 'Department sys_id' },
191
+ manager: { type: 'string', description: 'Manager sys_id' },
192
+ tasks: { type: 'array', items: { type: 'object' }, description: 'Onboarding tasks' }
193
+ },
194
+ required: ['employee_sys_id', 'start_date']
195
+ }
196
+ },
197
+ {
198
+ name: 'snow_manage_offboarding',
199
+ description: 'Manages employee offboarding using sn_hr_core_task table.',
200
+ inputSchema: {
201
+ type: 'object',
202
+ properties: {
203
+ employee_sys_id: { type: 'string', description: 'Employee sys_id' },
204
+ last_day: { type: 'string', description: 'Last working day' },
205
+ reason: { type: 'string', description: 'Departure reason' },
206
+ tasks: { type: 'array', items: { type: 'object' }, description: 'Offboarding tasks' }
207
+ },
208
+ required: ['employee_sys_id', 'last_day']
209
+ }
210
+ },
211
+ {
212
+ name: 'snow_get_hr_analytics',
213
+ description: 'Gets HR analytics from sn_hr_core_case table.',
214
+ inputSchema: {
215
+ type: 'object',
216
+ properties: {
217
+ metric: { type: 'string', description: 'case_volume, resolution_time, satisfaction' },
218
+ time_range: { type: 'string', description: 'Analysis period' },
219
+ department: { type: 'string', description: 'Filter by department' }
220
+ },
221
+ required: ['metric']
222
+ }
223
+ },
224
+ // Customer Service Management Tools
225
+ {
226
+ name: 'snow_create_csm_case',
227
+ description: 'Creates customer service case using sn_customerservice_case table.',
228
+ inputSchema: {
229
+ type: 'object',
230
+ properties: {
231
+ account: { type: 'string', description: 'Customer account sys_id' },
232
+ contact: { type: 'string', description: 'Contact sys_id' },
233
+ short_description: { type: 'string', description: 'Case description' },
234
+ category: { type: 'string', description: 'Case category' },
235
+ product: { type: 'string', description: 'Product sys_id' },
236
+ priority: { type: 'string', description: 'Priority level' },
237
+ channel: { type: 'string', description: 'Contact channel' }
238
+ },
239
+ required: ['account', 'short_description']
240
+ }
241
+ },
242
+ {
243
+ name: 'snow_manage_customer_account',
244
+ description: 'Manages customer account using sn_customerservice_account table.',
245
+ inputSchema: {
246
+ type: 'object',
247
+ properties: {
248
+ name: { type: 'string', description: 'Account name' },
249
+ industry: { type: 'string', description: 'Industry type' },
250
+ tier: { type: 'string', description: 'Customer tier' },
251
+ annual_revenue: { type: 'number', description: 'Annual revenue' },
252
+ primary_contact: { type: 'string', description: 'Primary contact sys_id' }
253
+ },
254
+ required: ['name']
255
+ }
256
+ },
257
+ {
258
+ name: 'snow_create_csm_communication',
259
+ description: 'Creates customer communication using sn_customerservice_communication table.',
260
+ inputSchema: {
261
+ type: 'object',
262
+ properties: {
263
+ case_sys_id: { type: 'string', description: 'Case sys_id' },
264
+ type: { type: 'string', description: 'email, phone, chat' },
265
+ direction: { type: 'string', description: 'inbound, outbound' },
266
+ subject: { type: 'string', description: 'Communication subject' },
267
+ body: { type: 'string', description: 'Message content' }
268
+ },
269
+ required: ['case_sys_id', 'type', 'body']
270
+ }
271
+ },
272
+ {
273
+ name: 'snow_get_customer_satisfaction',
274
+ description: 'Gets CSAT metrics from sn_customerservice_csat table.',
275
+ inputSchema: {
276
+ type: 'object',
277
+ properties: {
278
+ account: { type: 'string', description: 'Filter by account' },
279
+ time_range: { type: 'string', description: 'Analysis period' },
280
+ include_comments: { type: 'boolean', default: false }
281
+ }
282
+ }
283
+ },
284
+ // DevOps Tools
285
+ {
286
+ name: 'snow_create_devops_pipeline',
287
+ description: 'Creates DevOps pipeline using sn_devops_pipeline table.',
288
+ inputSchema: {
289
+ type: 'object',
290
+ properties: {
291
+ name: { type: 'string', description: 'Pipeline name' },
292
+ application: { type: 'string', description: 'Application sys_id' },
293
+ stages: { type: 'array', items: { type: 'object' }, description: 'Pipeline stages' },
294
+ repository: { type: 'string', description: 'Repository URL' },
295
+ branch: { type: 'string', description: 'Branch name' }
296
+ },
297
+ required: ['name', 'application']
298
+ }
299
+ },
300
+ {
301
+ name: 'snow_track_deployment',
302
+ description: 'Tracks deployment using sn_devops_deployment table.',
303
+ inputSchema: {
304
+ type: 'object',
305
+ properties: {
306
+ pipeline: { type: 'string', description: 'Pipeline sys_id' },
307
+ environment: { type: 'string', description: 'Target environment' },
308
+ version: { type: 'string', description: 'Version number' },
309
+ status: { type: 'string', description: 'Deployment status' },
310
+ change_request: { type: 'string', description: 'Associated change' }
311
+ },
312
+ required: ['pipeline', 'environment', 'version']
313
+ }
314
+ },
315
+ {
316
+ name: 'snow_manage_devops_change',
317
+ description: 'Manages DevOps change using sn_devops_change table.',
318
+ inputSchema: {
319
+ type: 'object',
320
+ properties: {
321
+ pipeline: { type: 'string', description: 'Pipeline sys_id' },
322
+ deployment: { type: 'string', description: 'Deployment sys_id' },
323
+ auto_approve: { type: 'boolean', default: false },
324
+ validation_results: { type: 'object', description: 'Validation data' }
325
+ },
326
+ required: ['pipeline', 'deployment']
327
+ }
328
+ },
329
+ {
330
+ name: 'snow_get_velocity_metrics',
331
+ description: 'Gets team velocity from sn_devops_velocity table.',
332
+ inputSchema: {
333
+ type: 'object',
334
+ properties: {
335
+ team: { type: 'string', description: 'Team sys_id' },
336
+ sprint: { type: 'string', description: 'Sprint identifier' },
337
+ time_range: { type: 'string', description: 'Analysis period' }
338
+ }
339
+ }
340
+ },
341
+ {
342
+ name: 'snow_create_devops_artifact',
343
+ description: 'Creates build artifact using sn_devops_artifact table.',
344
+ inputSchema: {
345
+ type: 'object',
346
+ properties: {
347
+ pipeline: { type: 'string', description: 'Pipeline sys_id' },
348
+ build_number: { type: 'string', description: 'Build number' },
349
+ artifact_type: { type: 'string', description: 'Artifact type' },
350
+ repository_url: { type: 'string', description: 'Artifact location' },
351
+ checksum: { type: 'string', description: 'Artifact checksum' }
352
+ },
353
+ required: ['pipeline', 'build_number']
354
+ }
355
+ }
356
+ ]
357
+ }));
358
+ this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
359
+ try {
360
+ const { name, arguments: args } = request.params;
361
+ // Execute with enhanced tracking
362
+ return await this.executeTool(name, async () => {
363
+ switch (name) {
364
+ // CMDB & Discovery
365
+ case 'snow_create_cmdb_ci':
366
+ return await this.createCMDBCI(args);
367
+ case 'snow_create_ci_relationship':
368
+ return await this.createCIRelationship(args);
369
+ case 'snow_discover_ci_dependencies':
370
+ return await this.discoverCIDependencies(args);
371
+ case 'snow_run_discovery':
372
+ return await this.runDiscovery(args);
373
+ case 'snow_get_discovery_status':
374
+ return await this.getDiscoveryStatus(args);
375
+ case 'snow_import_cmdb_data':
376
+ return await this.importCMDBData(args);
377
+ // Event Management
378
+ case 'snow_create_event':
379
+ return await this.createEvent(args);
380
+ case 'snow_create_alert_rule':
381
+ return await this.createAlertRule(args);
382
+ case 'snow_correlate_alerts':
383
+ return await this.correlateAlerts(args);
384
+ case 'snow_get_event_metrics':
385
+ return await this.getEventMetrics(args);
386
+ // HR Service Delivery
387
+ case 'snow_create_hr_case':
388
+ return await this.createHRCase(args);
389
+ case 'snow_manage_onboarding':
390
+ return await this.manageOnboarding(args);
391
+ case 'snow_manage_offboarding':
392
+ return await this.manageOffboarding(args);
393
+ case 'snow_get_hr_analytics':
394
+ return await this.getHRAnalytics(args);
395
+ // Customer Service Management
396
+ case 'snow_create_csm_case':
397
+ return await this.createCSMCase(args);
398
+ case 'snow_manage_customer_account':
399
+ return await this.manageCustomerAccount(args);
400
+ case 'snow_create_csm_communication':
401
+ return await this.createCSMCommunication(args);
402
+ case 'snow_get_customer_satisfaction':
403
+ return await this.getCustomerSatisfaction(args);
404
+ // DevOps
405
+ case 'snow_create_devops_pipeline':
406
+ return await this.createDevOpsPipeline(args);
407
+ case 'snow_track_deployment':
408
+ return await this.trackDeployment(args);
409
+ case 'snow_manage_devops_change':
410
+ return await this.manageDevOpsChange(args);
411
+ case 'snow_get_velocity_metrics':
412
+ return await this.getVelocityMetrics(args);
413
+ case 'snow_create_devops_artifact':
414
+ return await this.createDevOpsArtifact(args);
415
+ default:
416
+ throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
417
+ }
418
+ });
419
+ }
420
+ catch (error) {
421
+ if (error instanceof types_js_1.McpError)
422
+ throw error;
423
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Tool execution failed: ${error}`);
424
+ }
425
+ });
426
+ }
427
+ // CMDB & Discovery Methods
428
+ async createCMDBCI(args) {
429
+ this.logger.info('Creating CMDB CI...', {
430
+ ci_class: args.ci_class,
431
+ name: args.name
432
+ });
433
+ const ciData = {
434
+ name: args.name,
435
+ asset_tag: args.asset_tag || '',
436
+ serial_number: args.serial_number || '',
437
+ model_id: args.model_id || '',
438
+ location: args.location || '',
439
+ operational_status: args.operational_status || 'operational',
440
+ ...args.attributes
441
+ };
442
+ this.logger.progress(`Creating CI in ${args.ci_class}...`);
443
+ const response = await this.createRecord(args.ci_class, ciData);
444
+ if (!response.success) {
445
+ return this.createResponse(`❌ Failed to create CI: ${response.error}`);
446
+ }
447
+ const result = response.data;
448
+ this.logger.info('✅ CI created', {
449
+ sys_id: result.sys_id,
450
+ name: args.name
451
+ });
452
+ return this.createResponse(`✅ Configuration Item created!
453
+ 🖥️ **${args.name}**
454
+ 📦 Class: ${args.ci_class}
455
+ 🏷️ Asset Tag: ${args.asset_tag || 'N/A'}
456
+ 📍 Location: ${args.location || 'N/A'}
457
+ 🆔 sys_id: ${result.sys_id}
458
+
459
+ ✨ CI added to CMDB!`);
460
+ }
461
+ async createCIRelationship(args) {
462
+ this.logger.info('Creating CI relationship...', {
463
+ parent: args.parent,
464
+ child: args.child
465
+ });
466
+ const relData = {
467
+ parent: args.parent,
468
+ child: args.child,
469
+ type: args.type,
470
+ description: args.description || ''
471
+ };
472
+ this.logger.progress('Creating relationship...');
473
+ const response = await this.createRecord('cmdb_rel_ci', relData);
474
+ if (!response.success) {
475
+ return this.createResponse(`❌ Failed to create relationship: ${response.error}`);
476
+ }
477
+ this.logger.info('✅ Relationship created');
478
+ return this.createResponse(`✅ CI Relationship created!
479
+ 🔗 Parent → Child
480
+ 📝 Type: ${args.type}
481
+ 🆔 sys_id: ${response.data.sys_id}`);
482
+ }
483
+ async discoverCIDependencies(args) {
484
+ this.logger.info('Discovering CI dependencies...', {
485
+ ci_sys_id: args.ci_sys_id,
486
+ depth: args.depth
487
+ });
488
+ const direction = args.direction || 'both';
489
+ let query = '';
490
+ if (direction === 'upstream' || direction === 'both') {
491
+ query = `child=${args.ci_sys_id}`;
492
+ }
493
+ if (direction === 'downstream' || direction === 'both') {
494
+ query += query ? `^ORparent=${args.ci_sys_id}` : `parent=${args.ci_sys_id}`;
495
+ }
496
+ this.logger.progress('Analyzing dependencies...');
497
+ const response = await this.queryTable('cmdb_rel_ci', query, 100);
498
+ if (!response.success) {
499
+ return this.createResponse(`❌ Failed to discover dependencies: ${response.error}`);
500
+ }
501
+ const relationships = response.data.result;
502
+ this.logger.info(`Found ${relationships.length} dependencies`);
503
+ const depList = relationships.map((rel) => `🔗 ${rel.parent.display_value} → ${rel.child.display_value} (${rel.type.display_value})`).join('\n');
504
+ return this.createResponse(`🔍 CI Dependencies:\n\n${depList}\n\n✨ Total: ${relationships.length} relationship(s)`);
505
+ }
506
+ async runDiscovery(args) {
507
+ this.logger.info('Running discovery...', {
508
+ schedule_sys_id: args.schedule_sys_id
509
+ });
510
+ const discoveryData = {
511
+ schedule: args.schedule_sys_id,
512
+ ip_range: args.ip_range || '',
513
+ mid_server: args.mid_server || '',
514
+ state: 'starting',
515
+ started: new Date().toISOString()
516
+ };
517
+ this.logger.progress('Initiating discovery...');
518
+ const response = await this.createRecord('discovery_status', discoveryData);
519
+ if (!response.success) {
520
+ return this.createResponse(`❌ Failed to start discovery: ${response.error}`);
521
+ }
522
+ this.logger.info('✅ Discovery started');
523
+ return this.createResponse(`✅ Discovery started!
524
+ 🔍 Schedule: ${args.schedule_sys_id}
525
+ 🌐 IP Range: ${args.ip_range || 'Default'}
526
+ 🖥️ MID Server: ${args.mid_server || 'Auto-select'}
527
+ 🆔 Status ID: ${response.data.sys_id}
528
+
529
+ ⏳ Discovery in progress...`);
530
+ }
531
+ async getDiscoveryStatus(args) {
532
+ this.logger.info('Getting discovery status...');
533
+ let query = '';
534
+ if (args.schedule_sys_id) {
535
+ query = `schedule=${args.schedule_sys_id}`;
536
+ }
537
+ const response = await this.queryTable('discovery_status', query, args.limit || 10);
538
+ if (!response.success) {
539
+ return this.createResponse(`❌ Failed to get status: ${response.error}`);
540
+ }
541
+ const statuses = response.data.result;
542
+ if (!statuses.length) {
543
+ return this.createResponse(`❌ No discovery status found`);
544
+ }
545
+ const statusList = statuses.map((status) => `🔍 ${status.schedule?.display_value || 'Discovery'}
546
+ 📊 State: ${status.state}
547
+ ⏰ Started: ${status.started}
548
+ 🎯 Discovered: ${status.devices_discovered || 0} devices`).join('\n\n');
549
+ return this.createResponse(`📊 Discovery Status:\n\n${statusList}\n\n✨ ${statuses.length} discovery run(s)`);
550
+ }
551
+ async importCMDBData(args) {
552
+ this.logger.info('Importing CMDB data...', {
553
+ table_name: args.table_name,
554
+ records: args.data.length
555
+ });
556
+ const importSetData = {
557
+ table_name: args.table_name,
558
+ import_set_table: `u_import_${args.table_name}`,
559
+ transform_map: args.transform_map || '',
560
+ state: 'loading'
561
+ };
562
+ this.logger.progress('Creating import set...');
563
+ const importSet = await this.createRecord('sys_import_set', importSetData);
564
+ if (!importSet.success) {
565
+ return this.createResponse(`❌ Failed to create import set: ${importSet.error}`);
566
+ }
567
+ // Import data records
568
+ let imported = 0;
569
+ for (const record of args.data) {
570
+ const importRecord = await this.createRecord(importSetData.import_set_table, {
571
+ ...record,
572
+ sys_import_set: importSet.data.sys_id
573
+ });
574
+ if (importRecord.success)
575
+ imported++;
576
+ }
577
+ this.logger.info(`✅ Imported ${imported} records`);
578
+ return this.createResponse(`✅ CMDB Import completed!
579
+ 📋 Table: ${args.table_name}
580
+ 📊 Records: ${imported}/${args.data.length}
581
+ 🆔 Import Set: ${importSet.data.sys_id}
582
+
583
+ ✨ Data imported successfully!`);
584
+ }
585
+ // Event Management Methods
586
+ async createEvent(args) {
587
+ this.logger.info('Creating event...', {
588
+ source: args.source,
589
+ severity: args.severity
590
+ });
591
+ const eventData = {
592
+ source: args.source,
593
+ node: args.node,
594
+ type: args.type,
595
+ severity: args.severity,
596
+ description: args.description || '',
597
+ message_key: args.message_key || `${args.source}_${Date.now()}`,
598
+ metric_name: args.metric_name || '',
599
+ resource: args.resource || '',
600
+ time_of_event: new Date().toISOString()
601
+ };
602
+ this.logger.progress('Creating event...');
603
+ const response = await this.createRecord('em_event', eventData);
604
+ if (!response.success) {
605
+ return this.createResponse(`❌ Failed to create event: ${response.error}`);
606
+ }
607
+ this.logger.info('✅ Event created');
608
+ return this.createResponse(`✅ Event created!
609
+ 🚨 Source: ${args.source}
610
+ 📊 Severity: ${args.severity}
611
+ 🖥️ Node: ${args.node}
612
+ 🔑 Message Key: ${eventData.message_key}
613
+ 🆔 sys_id: ${response.data.sys_id}`);
614
+ }
615
+ async createAlertRule(args) {
616
+ this.logger.info('Creating alert rule...', { name: args.name });
617
+ const ruleData = {
618
+ name: args.name,
619
+ condition: args.condition,
620
+ threshold: args.threshold || 0,
621
+ action: args.action || '',
622
+ active: args.active !== false
623
+ };
624
+ this.logger.progress('Creating rule...');
625
+ const response = await this.createRecord('em_alert_rule', ruleData);
626
+ if (!response.success) {
627
+ return this.createResponse(`❌ Failed to create rule: ${response.error}`);
628
+ }
629
+ this.logger.info('✅ Alert rule created');
630
+ return this.createResponse(`✅ Alert rule created!
631
+ 📋 **${args.name}**
632
+ 🔍 Condition: ${args.condition}
633
+ ⚠️ Threshold: ${args.threshold || 'N/A'}
634
+ ✅ Active: ${args.active !== false}
635
+ 🆔 sys_id: ${response.data.sys_id}`);
636
+ }
637
+ async correlateAlerts(args) {
638
+ this.logger.info('Correlating alerts...', {
639
+ alerts: args.alerts.length
640
+ });
641
+ const correlationData = {
642
+ alerts: args.alerts.join(','),
643
+ correlation_rule: args.correlation_rule || '',
644
+ correlation_id: `CORR_${Date.now()}`,
645
+ state: 'correlated'
646
+ };
647
+ this.logger.progress('Correlating alerts...');
648
+ // Update alerts with correlation ID
649
+ for (const alertId of args.alerts) {
650
+ await this.updateRecord('em_alert', alertId, {
651
+ correlation_id: correlationData.correlation_id
652
+ });
653
+ }
654
+ if (args.create_incident) {
655
+ // Create incident from correlated alerts
656
+ const incidentData = {
657
+ short_description: `Correlated Alert: ${correlationData.correlation_id}`,
658
+ description: `Correlated ${args.alerts.length} alerts`,
659
+ priority: '2',
660
+ category: 'event'
661
+ };
662
+ const incident = await this.createRecord('incident', incidentData);
663
+ if (incident.success) {
664
+ return this.createResponse(`✅ Alerts correlated & incident created!
665
+ 🔗 Correlation ID: ${correlationData.correlation_id}
666
+ 📊 Alerts: ${args.alerts.length}
667
+ 🎫 Incident: ${incident.data.number}`);
668
+ }
669
+ }
670
+ this.logger.info('✅ Alerts correlated');
671
+ return this.createResponse(`✅ Alerts correlated!
672
+ 🔗 Correlation ID: ${correlationData.correlation_id}
673
+ 📊 Correlated: ${args.alerts.length} alerts`);
674
+ }
675
+ async getEventMetrics(args) {
676
+ this.logger.info('Getting event metrics...');
677
+ let query = '';
678
+ if (args.source)
679
+ query += `source=${args.source}`;
680
+ if (args.node)
681
+ query += `^node=${args.node}`;
682
+ this.logger.progress('Analyzing events...');
683
+ const response = await this.queryTable('em_event', query, 100);
684
+ if (!response.success) {
685
+ return this.createResponse(`❌ Failed to get metrics: ${response.error}`);
686
+ }
687
+ const events = response.data.result;
688
+ // Calculate metrics
689
+ const severityCounts = { '1': 0, '2': 0, '3': 0, '4': 0, '5': 0 };
690
+ events.forEach((event) => {
691
+ severityCounts[event.severity] = (severityCounts[event.severity] || 0) + 1;
692
+ });
693
+ return this.createResponse(`📊 Event Metrics:
694
+ 🚨 Critical: ${severityCounts['1']}
695
+ ⚠️ Major: ${severityCounts['2']}
696
+ ⚡ Minor: ${severityCounts['3']}
697
+ ℹ️ Warning: ${severityCounts['4']}
698
+ 📝 Info: ${severityCounts['5']}
699
+
700
+ ✨ Total: ${events.length} events`);
701
+ }
702
+ // HR Service Delivery Methods
703
+ async createHRCase(args) {
704
+ this.logger.info('Creating HR case...', {
705
+ subject_person: args.subject_person,
706
+ category: args.category
707
+ });
708
+ const caseData = {
709
+ subject_person: args.subject_person,
710
+ short_description: args.short_description,
711
+ category: args.category || '',
712
+ subcategory: args.subcategory || '',
713
+ priority: args.priority || '3',
714
+ confidential: args.confidential || false,
715
+ hr_service: args.hr_service || '',
716
+ state: 'new'
717
+ };
718
+ this.logger.progress('Creating HR case...');
719
+ const response = await this.createRecord('sn_hr_core_case', caseData);
720
+ if (!response.success) {
721
+ return this.createResponse(`❌ Failed to create HR case: ${response.error}`);
722
+ }
723
+ const result = response.data;
724
+ this.logger.info('✅ HR case created', { number: result.number });
725
+ return this.createResponse(`✅ HR Case created!
726
+ 📋 **${result.number}**
727
+ 👤 Employee: ${args.subject_person}
728
+ 📁 Category: ${args.category || 'General'}
729
+ 🔒 Confidential: ${args.confidential ? 'Yes' : 'No'}
730
+ 🆔 sys_id: ${result.sys_id}
731
+
732
+ ✨ HR case ready for processing!`);
733
+ }
734
+ async manageOnboarding(args) {
735
+ this.logger.info('Managing onboarding...', {
736
+ employee: args.employee_sys_id,
737
+ start_date: args.start_date
738
+ });
739
+ // Create onboarding case
740
+ const onboardingCase = await this.createRecord('sn_hr_core_case', {
741
+ subject_person: args.employee_sys_id,
742
+ short_description: `Onboarding - Start Date: ${args.start_date}`,
743
+ category: 'onboarding',
744
+ hr_service: 'employee_onboarding',
745
+ state: 'in_progress'
746
+ });
747
+ if (!onboardingCase.success) {
748
+ return this.createResponse(`❌ Failed to create onboarding: ${onboardingCase.error}`);
749
+ }
750
+ // Create onboarding tasks
751
+ const tasks = args.tasks || [
752
+ { name: 'Provision equipment', days_before: 3 },
753
+ { name: 'Create accounts', days_before: 2 },
754
+ { name: 'Schedule orientation', days_before: 1 }
755
+ ];
756
+ let createdTasks = 0;
757
+ for (const task of tasks) {
758
+ const taskData = {
759
+ parent: onboardingCase.data.sys_id,
760
+ short_description: task.name,
761
+ assigned_to: task.assigned_to || '',
762
+ due_date: task.due_date || args.start_date
763
+ };
764
+ const taskResult = await this.createRecord('sn_hr_core_task', taskData);
765
+ if (taskResult.success)
766
+ createdTasks++;
767
+ }
768
+ this.logger.info('✅ Onboarding created', {
769
+ case: onboardingCase.data.number,
770
+ tasks: createdTasks
771
+ });
772
+ return this.createResponse(`✅ Onboarding initiated!
773
+ 📋 Case: ${onboardingCase.data.number}
774
+ 👤 Employee: ${args.employee_sys_id}
775
+ 📅 Start Date: ${args.start_date}
776
+ 🏢 Department: ${args.department || 'TBD'}
777
+ 👨‍💼 Manager: ${args.manager || 'TBD'}
778
+ 📌 Tasks Created: ${createdTasks}
779
+
780
+ ✨ Onboarding process started!`);
781
+ }
782
+ async manageOffboarding(args) {
783
+ this.logger.info('Managing offboarding...', {
784
+ employee: args.employee_sys_id,
785
+ last_day: args.last_day
786
+ });
787
+ // Create offboarding case
788
+ const offboardingCase = await this.createRecord('sn_hr_core_case', {
789
+ subject_person: args.employee_sys_id,
790
+ short_description: `Offboarding - Last Day: ${args.last_day}`,
791
+ category: 'offboarding',
792
+ hr_service: 'employee_offboarding',
793
+ u_reason: args.reason || '',
794
+ state: 'in_progress'
795
+ });
796
+ if (!offboardingCase.success) {
797
+ return this.createResponse(`❌ Failed to create offboarding: ${offboardingCase.error}`);
798
+ }
799
+ // Create offboarding tasks
800
+ const tasks = args.tasks || [
801
+ { name: 'Collect equipment', days_after: 0 },
802
+ { name: 'Revoke access', days_after: 1 },
803
+ { name: 'Exit interview', days_before: 1 }
804
+ ];
805
+ let createdTasks = 0;
806
+ for (const task of tasks) {
807
+ const taskResult = await this.createRecord('sn_hr_core_task', {
808
+ parent: offboardingCase.data.sys_id,
809
+ short_description: task.name
810
+ });
811
+ if (taskResult.success)
812
+ createdTasks++;
813
+ }
814
+ this.logger.info('✅ Offboarding created');
815
+ return this.createResponse(`✅ Offboarding initiated!
816
+ 📋 Case: ${offboardingCase.data.number}
817
+ 👤 Employee: ${args.employee_sys_id}
818
+ 📅 Last Day: ${args.last_day}
819
+ 📝 Reason: ${args.reason || 'Not specified'}
820
+ 📌 Tasks Created: ${createdTasks}
821
+
822
+ ✨ Offboarding process started!`);
823
+ }
824
+ async getHRAnalytics(args) {
825
+ this.logger.info('Getting HR analytics...', { metric: args.metric });
826
+ let query = '';
827
+ if (args.department)
828
+ query = `department=${args.department}`;
829
+ const response = await this.queryTable('sn_hr_core_case', query, 100);
830
+ if (!response.success) {
831
+ return this.createResponse(`❌ Failed to get analytics: ${response.error}`);
832
+ }
833
+ const cases = response.data.result;
834
+ if (args.metric === 'case_volume') {
835
+ const categoryCounts = {};
836
+ cases.forEach((c) => {
837
+ categoryCounts[c.category] = (categoryCounts[c.category] || 0) + 1;
838
+ });
839
+ const breakdown = Object.entries(categoryCounts)
840
+ .map(([cat, count]) => ` ${cat}: ${count}`)
841
+ .join('\n');
842
+ return this.createResponse(`📊 HR Case Volume:\n${breakdown}\n\n✨ Total: ${cases.length} cases`);
843
+ }
844
+ return this.createResponse(`📊 HR Analytics:
845
+ 📋 Total Cases: ${cases.length}
846
+ 📈 Metric: ${args.metric}
847
+ 📅 Period: ${args.time_range || 'All time'}`);
848
+ }
849
+ // Customer Service Management Methods
850
+ async createCSMCase(args) {
851
+ this.logger.info('Creating customer case...', {
852
+ account: args.account,
853
+ short_description: args.short_description
854
+ });
855
+ const caseData = {
856
+ account: args.account,
857
+ contact: args.contact || '',
858
+ short_description: args.short_description,
859
+ category: args.category || '',
860
+ product: args.product || '',
861
+ priority: args.priority || '3',
862
+ channel: args.channel || 'web',
863
+ state: 'new'
864
+ };
865
+ this.logger.progress('Creating customer case...');
866
+ const response = await this.createRecord('sn_customerservice_case', caseData);
867
+ if (!response.success) {
868
+ return this.createResponse(`❌ Failed to create case: ${response.error}`);
869
+ }
870
+ const result = response.data;
871
+ this.logger.info('✅ Customer case created', { number: result.number });
872
+ return this.createResponse(`✅ Customer Case created!
873
+ 📋 **${result.number}**
874
+ 🏢 Account: ${args.account}
875
+ 📝 ${args.short_description}
876
+ 📱 Channel: ${args.channel || 'Web'}
877
+ 🆔 sys_id: ${result.sys_id}
878
+
879
+ ✨ Case ready for support team!`);
880
+ }
881
+ async manageCustomerAccount(args) {
882
+ this.logger.info('Managing customer account...', { name: args.name });
883
+ const accountData = {
884
+ name: args.name,
885
+ industry: args.industry || '',
886
+ tier: args.tier || 'standard',
887
+ annual_revenue: args.annual_revenue || 0,
888
+ primary_contact: args.primary_contact || ''
889
+ };
890
+ this.logger.progress('Creating/updating account...');
891
+ const response = await this.createRecord('sn_customerservice_account', accountData);
892
+ if (!response.success) {
893
+ return this.createResponse(`❌ Failed to manage account: ${response.error}`);
894
+ }
895
+ this.logger.info('✅ Account managed');
896
+ return this.createResponse(`✅ Customer Account created!
897
+ 🏢 **${args.name}**
898
+ 🏭 Industry: ${args.industry || 'N/A'}
899
+ ⭐ Tier: ${args.tier || 'Standard'}
900
+ 💰 Revenue: ${args.annual_revenue || 'N/A'}
901
+ 🆔 sys_id: ${response.data.sys_id}`);
902
+ }
903
+ async createCSMCommunication(args) {
904
+ this.logger.info('Creating communication...', {
905
+ case_sys_id: args.case_sys_id,
906
+ type: args.type
907
+ });
908
+ const commData = {
909
+ case: args.case_sys_id,
910
+ type: args.type,
911
+ direction: args.direction || 'outbound',
912
+ subject: args.subject || '',
913
+ body: args.body,
914
+ created: new Date().toISOString()
915
+ };
916
+ this.logger.progress('Recording communication...');
917
+ const response = await this.createRecord('sn_customerservice_communication', commData);
918
+ if (!response.success) {
919
+ return this.createResponse(`❌ Failed to create communication: ${response.error}`);
920
+ }
921
+ this.logger.info('✅ Communication recorded');
922
+ return this.createResponse(`✅ Communication recorded!
923
+ 📧 Type: ${args.type}
924
+ 📤 Direction: ${args.direction || 'Outbound'}
925
+ 📝 Subject: ${args.subject || 'N/A'}
926
+ 🆔 sys_id: ${response.data.sys_id}`);
927
+ }
928
+ async getCustomerSatisfaction(args) {
929
+ this.logger.info('Getting CSAT metrics...');
930
+ let query = '';
931
+ if (args.account)
932
+ query = `account=${args.account}`;
933
+ const response = await this.queryTable('sn_customerservice_csat', query, 100);
934
+ if (!response.success) {
935
+ return this.createResponse(`❌ Failed to get CSAT: ${response.error}`);
936
+ }
937
+ const surveys = response.data.result;
938
+ if (!surveys.length) {
939
+ return this.createResponse(`❌ No CSAT data found`);
940
+ }
941
+ // Calculate average CSAT
942
+ const scores = surveys.map((s) => parseFloat(s.score || 0));
943
+ const avgScore = (scores.reduce((a, b) => a + b, 0) / scores.length).toFixed(1);
944
+ let result = `📊 Customer Satisfaction:
945
+ ⭐ Average Score: ${avgScore}/5
946
+ 📋 Responses: ${surveys.length}
947
+ 📅 Period: ${args.time_range || 'All time'}`;
948
+ if (args.include_comments) {
949
+ const comments = surveys
950
+ .filter((s) => s.comments)
951
+ .slice(0, 3)
952
+ .map((s) => ` 💬 "${s.comments}"`)
953
+ .join('\n');
954
+ if (comments) {
955
+ result += `\n\nRecent Comments:\n${comments}`;
956
+ }
957
+ }
958
+ return this.createResponse(result);
959
+ }
960
+ // DevOps Methods
961
+ async createDevOpsPipeline(args) {
962
+ this.logger.info('Creating DevOps pipeline...', {
963
+ name: args.name,
964
+ application: args.application
965
+ });
966
+ const pipelineData = {
967
+ name: args.name,
968
+ application: args.application,
969
+ stages: JSON.stringify(args.stages || []),
970
+ repository: args.repository || '',
971
+ branch: args.branch || 'main',
972
+ active: true
973
+ };
974
+ this.logger.progress('Creating pipeline...');
975
+ const response = await this.createRecord('sn_devops_pipeline', pipelineData);
976
+ if (!response.success) {
977
+ return this.createResponse(`❌ Failed to create pipeline: ${response.error}`);
978
+ }
979
+ const result = response.data;
980
+ this.logger.info('✅ Pipeline created', { sys_id: result.sys_id });
981
+ return this.createResponse(`✅ DevOps Pipeline created!
982
+ 🚀 **${args.name}**
983
+ 📱 Application: ${args.application}
984
+ 📦 Repository: ${args.repository || 'N/A'}
985
+ 🌿 Branch: ${args.branch || 'main'}
986
+ 📊 Stages: ${args.stages?.length || 0}
987
+ 🆔 sys_id: ${result.sys_id}
988
+
989
+ ✨ Pipeline ready for deployments!`);
990
+ }
991
+ async trackDeployment(args) {
992
+ this.logger.info('Tracking deployment...', {
993
+ pipeline: args.pipeline,
994
+ environment: args.environment,
995
+ version: args.version
996
+ });
997
+ const deploymentData = {
998
+ pipeline: args.pipeline,
999
+ environment: args.environment,
1000
+ version: args.version,
1001
+ status: args.status || 'in_progress',
1002
+ change_request: args.change_request || '',
1003
+ deployed_on: new Date().toISOString()
1004
+ };
1005
+ this.logger.progress('Recording deployment...');
1006
+ const response = await this.createRecord('sn_devops_deployment', deploymentData);
1007
+ if (!response.success) {
1008
+ return this.createResponse(`❌ Failed to track deployment: ${response.error}`);
1009
+ }
1010
+ this.logger.info('✅ Deployment tracked');
1011
+ return this.createResponse(`✅ Deployment tracked!
1012
+ 🚀 Version: ${args.version}
1013
+ 🌍 Environment: ${args.environment}
1014
+ 📊 Status: ${args.status || 'In Progress'}
1015
+ 🔄 Change: ${args.change_request || 'N/A'}
1016
+ 🆔 sys_id: ${response.data.sys_id}`);
1017
+ }
1018
+ async manageDevOpsChange(args) {
1019
+ this.logger.info('Managing DevOps change...', {
1020
+ pipeline: args.pipeline,
1021
+ deployment: args.deployment
1022
+ });
1023
+ const changeData = {
1024
+ pipeline: args.pipeline,
1025
+ deployment: args.deployment,
1026
+ auto_approve: args.auto_approve || false,
1027
+ validation_results: JSON.stringify(args.validation_results || {}),
1028
+ state: args.auto_approve ? 'approved' : 'pending'
1029
+ };
1030
+ this.logger.progress('Processing change...');
1031
+ const response = await this.createRecord('sn_devops_change', changeData);
1032
+ if (!response.success) {
1033
+ return this.createResponse(`❌ Failed to manage change: ${response.error}`);
1034
+ }
1035
+ this.logger.info('✅ Change processed');
1036
+ return this.createResponse(`✅ DevOps change processed!
1037
+ 🔄 Pipeline: ${args.pipeline}
1038
+ 🚀 Deployment: ${args.deployment}
1039
+ ✅ Auto-approve: ${args.auto_approve ? 'Yes' : 'No'}
1040
+ 📊 State: ${args.auto_approve ? 'Approved' : 'Pending'}
1041
+ 🆔 sys_id: ${response.data.sys_id}`);
1042
+ }
1043
+ async getVelocityMetrics(args) {
1044
+ this.logger.info('Getting velocity metrics...');
1045
+ let query = '';
1046
+ if (args.team)
1047
+ query = `team=${args.team}`;
1048
+ if (args.sprint)
1049
+ query += `^sprint=${args.sprint}`;
1050
+ const response = await this.queryTable('sn_devops_velocity', query, 50);
1051
+ if (!response.success) {
1052
+ return this.createResponse(`❌ Failed to get velocity: ${response.error}`);
1053
+ }
1054
+ const metrics = response.data.result;
1055
+ if (!metrics.length) {
1056
+ return this.createResponse(`❌ No velocity data found`);
1057
+ }
1058
+ // Calculate velocity
1059
+ const storyPoints = metrics.map((m) => parseFloat(m.story_points || 0));
1060
+ const avgVelocity = (storyPoints.reduce((a, b) => a + b, 0) / storyPoints.length).toFixed(1);
1061
+ return this.createResponse(`📊 Team Velocity:
1062
+ 🚀 Average: ${avgVelocity} story points/sprint
1063
+ 📈 Sprints: ${metrics.length}
1064
+ 👥 Team: ${args.team || 'All teams'}
1065
+ 📅 Period: ${args.time_range || 'Recent sprints'}
1066
+
1067
+ ✨ Velocity trending ${parseFloat(avgVelocity) > 20 ? 'up' : 'stable'}!`);
1068
+ }
1069
+ async createDevOpsArtifact(args) {
1070
+ this.logger.info('Creating build artifact...', {
1071
+ pipeline: args.pipeline,
1072
+ build_number: args.build_number
1073
+ });
1074
+ const artifactData = {
1075
+ pipeline: args.pipeline,
1076
+ build_number: args.build_number,
1077
+ artifact_type: args.artifact_type || 'build',
1078
+ repository_url: args.repository_url || '',
1079
+ checksum: args.checksum || '',
1080
+ created: new Date().toISOString()
1081
+ };
1082
+ this.logger.progress('Recording artifact...');
1083
+ const response = await this.createRecord('sn_devops_artifact', artifactData);
1084
+ if (!response.success) {
1085
+ return this.createResponse(`❌ Failed to create artifact: ${response.error}`);
1086
+ }
1087
+ this.logger.info('✅ Artifact created');
1088
+ return this.createResponse(`✅ Build artifact recorded!
1089
+ 📦 Build: #${args.build_number}
1090
+ 🔧 Type: ${args.artifact_type || 'Build'}
1091
+ 🔗 Repository: ${args.repository_url || 'N/A'}
1092
+ 🔐 Checksum: ${args.checksum ? '✓' : 'N/A'}
1093
+ 🆔 sys_id: ${response.data.sys_id}
1094
+
1095
+ ✨ Artifact ready for deployment!`);
1096
+ }
1097
+ async start() {
1098
+ const transport = new stdio_js_1.StdioServerTransport();
1099
+ await this.server.connect(transport);
1100
+ // Log ready state
1101
+ this.logger.info('🚀 ServiceNow CMDB, Event, HR, CSM & DevOps MCP Server (Enhanced) running');
1102
+ this.logger.info('📊 Token tracking enabled');
1103
+ this.logger.info('⏳ Progress indicators active');
1104
+ }
1105
+ }
1106
+ // Start the enhanced server
1107
+ const server = new ServiceNowCMDBEventHRCSMDevOpsMCPEnhanced();
1108
+ server.start().catch((error) => {
1109
+ console.error('Failed to start enhanced server:', error);
1110
+ process.exit(1);
1111
+ });
1112
+ //# sourceMappingURL=servicenow-cmdb-event-hr-csm-devops-mcp-enhanced.js.map