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.
- package/dist/dynamic-version.js +1 -1
- package/dist/mcp/servicenow-change-virtualagent-pa-mcp-enhanced.d.ts +7 -0
- package/dist/mcp/servicenow-change-virtualagent-pa-mcp-enhanced.js +816 -0
- package/dist/mcp/servicenow-cmdb-event-hr-csm-devops-mcp-enhanced.d.ts +7 -0
- package/dist/mcp/servicenow-cmdb-event-hr-csm-devops-mcp-enhanced.js +1112 -0
- package/dist/mcp/servicenow-flow-workspace-mobile-mcp-enhanced.d.ts +7 -0
- package/dist/mcp/servicenow-flow-workspace-mobile-mcp-enhanced.js +860 -0
- package/dist/mcp/servicenow-knowledge-catalog-mcp-enhanced.js +503 -1
- package/dist/mcp/shared/enhanced-base-mcp-server.d.ts +8 -0
- package/dist/mcp/shared/enhanced-base-mcp-server.js +24 -0
- package/dist/mcp/shared/mcp-logger.js +2 -1
- package/package.json +2 -2
|
@@ -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
|