snow-flow 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/{.claude/mcp-config.json → .mcp.json} +13 -12
  2. package/.releaserc.json +47 -0
  3. package/README.md +6 -0
  4. package/package.json +1 -1
  5. package/.claude/claude-settings.json +0 -15
  6. package/.claude/commands/analysis/README.md +0 -9
  7. package/.claude/commands/automation/README.md +0 -9
  8. package/.claude/commands/github/README.md +0 -11
  9. package/.claude/commands/helpers/standard-checkpoint-hooks.sh +0 -179
  10. package/.claude/commands/hooks/README.md +0 -11
  11. package/.claude/commands/monitoring/README.md +0 -9
  12. package/.claude/commands/optimization/README.md +0 -9
  13. package/.claude/commands/training/README.md +0 -9
  14. package/.claude/commands/workflows/README.md +0 -9
  15. package/.claude/config.json +0 -36
  16. package/.claude/helpers/github-setup.sh +0 -28
  17. package/.claude/helpers/quick-start.sh +0 -19
  18. package/.claude/helpers/setup-mcp.sh +0 -18
  19. package/.claude/settings.json +0 -114
  20. package/.claude/settings.local.json +0 -33
  21. package/.claude-flow/metrics/agent-metrics.json +0 -1
  22. package/.claude-flow/metrics/performance.json +0 -9
  23. package/.claude-flow/metrics/system-metrics.json +0 -15986
  24. package/.claude-flow/metrics/task-metrics.json +0 -10
  25. package/.roo/README.md +0 -402
  26. package/.roo/mcp-list.txt +0 -257
  27. package/.roo/mcp.json +0 -32
  28. package/.roo/workflows/basic-tdd.json +0 -32
  29. package/.roomodes +0 -201
  30. package/CLAUDE.md +0 -393
  31. package/bin/snow-flow.js +0 -3
  32. package/dist/cli.js.bak +0 -2052
  33. package/dist/config/snow-flow-config.d.ts +0 -1492
  34. package/dist/config/snow-flow-config.js +0 -938
  35. package/scripts/create-env.js +0 -91
  36. package/scripts/postinstall.js +0 -30
  37. package/scripts/register-mcp-servers.js +0 -210
  38. package/scripts/reset-mcp-servers.js +0 -246
  39. package/scripts/setup-mcp.js +0 -106
  40. package/scripts/update-version.js +0 -31
  41. package/src/agents/README.md +0 -192
  42. package/src/agents/base-agent.ts +0 -251
  43. package/src/agents/coordinator.ts +0 -971
  44. package/src/agents/index.ts +0 -18
  45. package/src/agents/queen-403-handler.ts +0 -230
  46. package/src/agents/queen-agent.ts +0 -1399
  47. package/src/agents/script-writer-agent.ts +0 -769
  48. package/src/agents/security-agent.ts +0 -726
  49. package/src/agents/widget-creator-agent.ts +0 -568
  50. package/src/api/error-handling.ts +0 -1758
  51. package/src/api/natural-language-mapper.ts +0 -630
  52. package/src/api/performance-optimizer.ts +0 -891
  53. package/src/api/transaction-manager.ts +0 -754
  54. package/src/cli/deploy-artifact.ts +0 -304
  55. package/src/cli/snow-flow-cli-integration.ts +0 -434
  56. package/src/cli.ts +0 -4455
  57. package/src/cli.ts.bak +0 -5616
  58. package/src/compliance/advanced-compliance-system.ts +0 -1268
  59. package/src/compliance/index.ts +0 -19
  60. package/src/config/snow-flow-config.ts +0 -1019
  61. package/src/documentation/index.ts +0 -16
  62. package/src/documentation/self-documenting-system.ts +0 -1421
  63. package/src/dynamic-version.ts +0 -44
  64. package/src/healing/index.ts +0 -20
  65. package/src/healing/self-healing-system.ts +0 -1435
  66. package/src/health/README.md +0 -161
  67. package/src/health/system-health.ts +0 -995
  68. package/src/index.ts +0 -60
  69. package/src/intelligence/acl-analyzer.ts +0 -377
  70. package/src/intelligence/auto-resolution-engine.ts +0 -643
  71. package/src/intelligence/gap-analysis-engine.ts +0 -488
  72. package/src/intelligence/manual-instructions-generator.ts +0 -744
  73. package/src/intelligence/mcp-coverage-analyzer.ts +0 -708
  74. package/src/intelligence/multi-pass-requirements-analyzer.ts +0 -603
  75. package/src/intelligence/performance-recommendations-engine.ts +0 -1223
  76. package/src/intelligence/requirements-analyzer.ts +0 -1148
  77. package/src/intelligence/task-analyzer.ts +0 -628
  78. package/src/managers/scope-manager.ts +0 -555
  79. package/src/mcp/advanced/servicenow-advanced-features-mcp.ts +0 -16110
  80. package/src/mcp/base-mcp-server.ts +0 -660
  81. package/src/mcp/http-transport-wrapper.ts +0 -426
  82. package/src/mcp/service-discovery-client.ts +0 -312
  83. package/src/mcp/servicenow-automation-mcp-refactored.ts +0 -678
  84. package/src/mcp/servicenow-automation-mcp.ts +0 -838
  85. package/src/mcp/servicenow-deployment-mcp-refactored.ts +0 -1292
  86. package/src/mcp/servicenow-deployment-mcp.ts +0 -7244
  87. package/src/mcp/servicenow-graph-memory-mcp-refactored.ts +0 -721
  88. package/src/mcp/servicenow-graph-memory-mcp.ts +0 -832
  89. package/src/mcp/servicenow-integration-mcp-refactored.ts +0 -655
  90. package/src/mcp/servicenow-integration-mcp.ts +0 -819
  91. package/src/mcp/servicenow-intelligent-mcp-refactored.ts +0 -977
  92. package/src/mcp/servicenow-intelligent-mcp.ts +0 -4638
  93. package/src/mcp/servicenow-mcp-server.ts +0 -728
  94. package/src/mcp/servicenow-memory-mcp.ts +0 -474
  95. package/src/mcp/servicenow-operations-mcp-refactored.ts +0 -1995
  96. package/src/mcp/servicenow-operations-mcp.ts +0 -3384
  97. package/src/mcp/servicenow-platform-development-mcp-refactored.ts +0 -611
  98. package/src/mcp/servicenow-platform-development-mcp.ts +0 -970
  99. package/src/mcp/servicenow-progressive-indexer.ts +0 -370
  100. package/src/mcp/servicenow-reporting-analytics-mcp-refactored.ts +0 -695
  101. package/src/mcp/servicenow-reporting-analytics-mcp.ts +0 -1123
  102. package/src/mcp/servicenow-security-compliance-mcp-refactored.ts +0 -642
  103. package/src/mcp/servicenow-security-compliance-mcp.ts +0 -1157
  104. package/src/mcp/servicenow-update-set-mcp-refactored.ts +0 -751
  105. package/src/mcp/servicenow-update-set-mcp.ts +0 -811
  106. package/src/mcp/shared/agent-context-provider.ts +0 -365
  107. package/src/mcp/shared/base-mcp-server.ts +0 -2463
  108. package/src/mcp/shared/mcp-memory-manager.ts +0 -540
  109. package/src/mcp/shared/mcp-resource-manager.ts +0 -367
  110. package/src/mcp/snow-flow-mcp.ts +0 -911
  111. package/src/mcp/start-all-mcp-servers.ts +0 -102
  112. package/src/mcp/start-servicenow-mcp.ts +0 -67
  113. package/src/monitoring/enhanced-monitoring-system.ts +0 -1345
  114. package/src/monitoring/performance-tracker.ts +0 -777
  115. package/src/optimization/cost-optimization-engine.ts +0 -1125
  116. package/src/optimization/index.ts +0 -10
  117. package/src/queen/README.md +0 -403
  118. package/src/queen/agent-factory.ts +0 -574
  119. package/src/queen/index.ts +0 -94
  120. package/src/queen/mcp-execution-bridge.ts +0 -681
  121. package/src/queen/neural-learning.ts +0 -319
  122. package/src/queen/parallel-agent-engine.ts +0 -848
  123. package/src/queen/queen-memory-system.ts +0 -490
  124. package/src/queen/queen-memory.ts +0 -456
  125. package/src/queen/servicenow-queen.ts +0 -1029
  126. package/src/queen/types.ts +0 -87
  127. package/src/rollback/smart-rollback-system.ts +0 -866
  128. package/src/schemas/deployment.schema.json +0 -58
  129. package/src/schemas/flow.schema.json +0 -79
  130. package/src/schemas/widget.schema.json +0 -72
  131. package/src/snow-flow-system.ts +0 -541
  132. package/src/sparc/sparc-help.ts +0 -49
  133. package/src/sparc/team-sparc.ts +0 -88
  134. package/src/strategies/global-scope-strategy.ts +0 -736
  135. package/src/templates/base/application.template.json +0 -45
  136. package/src/templates/base/business_rule.template.json +0 -33
  137. package/src/templates/base/script_include.template.json +0 -18
  138. package/src/templates/base/table.template.json +0 -64
  139. package/src/templates/base/widget.template.json +0 -25
  140. package/src/templates/patterns/composite.incident-management.template.json +0 -140
  141. package/src/templates/patterns/widget.dashboard.template.json +0 -238
  142. package/src/templates/patterns/widget.datatable.template.json +0 -292
  143. package/src/testing/integration-test-suite.ts +0 -1276
  144. package/src/types/index.ts +0 -183
  145. package/src/types/neo4j-driver.d.ts +0 -23
  146. package/src/types/servicenow.types.ts +0 -307
  147. package/src/types/snow-flow.types.ts +0 -186
  148. package/src/types/todo.types.ts +0 -70
  149. package/src/utils/action-type-cache.ts +0 -286
  150. package/src/utils/agent-detector.ts +0 -573
  151. package/src/utils/artifact-tracker.ts +0 -379
  152. package/src/utils/dependency-detector.ts +0 -233
  153. package/src/utils/deployment-metadata-handler.ts +0 -518
  154. package/src/utils/error-recovery.ts +0 -680
  155. package/src/utils/logger.ts +0 -60
  156. package/src/utils/mcp-auth-middleware.ts +0 -262
  157. package/src/utils/mcp-config-manager.ts +0 -270
  158. package/src/utils/mcp-server-manager.ts +0 -446
  159. package/src/utils/mcp-tool-registry.ts +0 -298
  160. package/src/utils/migrate-snow-flow.ts +0 -98
  161. package/src/utils/oauth-html-templates.ts +0 -188
  162. package/src/utils/scope-utils.ts +0 -443
  163. package/src/utils/servicenow-client.ts +0 -3321
  164. package/src/utils/servicenow-id-generator.ts +0 -181
  165. package/src/utils/snow-memory-manager.ts +0 -605
  166. package/src/utils/snow-oauth.ts +0 -797
  167. package/src/utils/template-engine.ts +0 -463
  168. package/src/utils/theme-manager.ts +0 -295
  169. package/src/utils/unified-auth-store.ts +0 -222
  170. package/src/utils/update-set-importer.ts +0 -422
  171. package/src/utils/update-set-xml-packager.ts +0 -371
  172. package/src/utils/widget-template-generator.ts +0 -1744
  173. package/src/version.ts +0 -1950
@@ -1,1995 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * ServiceNow Operations MCP Server - REFACTORED
4
- * Uses BaseMCPServer to eliminate code duplication
5
- *
6
- * Handles operational data queries, incident management, and intelligent analysis
7
- * Features:
8
- * - Incident, Request, Problem, Change management
9
- * - CMDB and User management
10
- * - Intelligent incident _analysis and auto-resolution
11
- * - Pattern recognition and root cause analysis
12
- * - Knowledge base integration
13
- * - Predictive analytics
14
- */
15
-
16
- import { BaseMCPServer, ToolResult } from './base-mcp-server.js';
17
- import { Tool } from '@modelcontextprotocol/sdk/types.js';
18
- import { generateMockSysId, generateRequestNumber } from '../utils/servicenow-id-generator.js';
19
-
20
- // Operational table mappings for ServiceNow
21
- const operationalTableMapping = {
22
- // ITIL Core Processes
23
- incident: 'incident',
24
- request: 'sc_request',
25
- request_item: 'sc_req_item',
26
- problem: 'problem',
27
- change_request: 'change_request',
28
-
29
- // Service Catalog
30
- catalog: 'sc_catalog',
31
- catalog_item: 'sc_cat_item',
32
- catalog_category: 'sc_category',
33
- catalog_variable: 'item_option_new',
34
- catalog_variable_set: 'io_set_item',
35
- catalog_ui_policy: 'catalog_ui_policy',
36
- catalog_client_script: 'catalog_script_client',
37
- catalog_template: 'sc_template',
38
-
39
- // Task Management
40
- task: 'task',
41
- incident_task: 'incident_task',
42
- problem_task: 'problem_task',
43
- change_task: 'change_task',
44
- approval: 'sysapproval_approver',
45
-
46
- // User & Group Management
47
- user: 'sys_user',
48
- user_group: 'sys_user_group',
49
- user_role: 'sys_user_has_role',
50
-
51
- // CMDB (Configuration Management Database)
52
- configuration_item: 'cmdb_ci',
53
- server: 'cmdb_ci_server',
54
- application: 'cmdb_ci_application',
55
- database: 'cmdb_ci_database',
56
- network_device: 'cmdb_ci_network_device',
57
- service: 'cmdb_ci_service',
58
-
59
- // Knowledge Management
60
- knowledge_base: 'kb_knowledge_base',
61
- knowledge: 'kb_knowledge',
62
-
63
- // Metrics & Analytics
64
- metric: 'sys_metric',
65
- metric_instance: 'sys_metric_instance',
66
-
67
- // Notifications
68
- notification: 'sysevent_email_action',
69
- email_log: 'sys_email'
70
- };
71
-
72
- interface IncidentAnalysis {
73
- incident_id: string;
74
- patterns_found: string[];
75
- root_cause__analysis: string;
76
- suggested_resolution: string[];
77
- confidence_score: number;
78
- similar_incidents: any[];
79
- knowledge_articles: any[];
80
- automated_actions: string[];
81
- }
82
-
83
- export class ServiceNowOperationsMCP extends BaseMCPServer {
84
- constructor() {
85
- super({
86
- name: 'servicenow-operations',
87
- version: '2.0.0',
88
- description: 'Operations management server with BaseMCPServer pattern'
89
- });
90
- }
91
-
92
- protected setupTools(): void {
93
- // Tools are set up via getTools() method
94
- }
95
-
96
- protected getTools(): Tool[] {
97
- return [
98
- {
99
- name: 'snow_query_incidents',
100
- description: 'Advanced incident querying with filters and _analysis',
101
- inputSchema: {
102
- type: 'object',
103
- properties: {
104
- query: { type: 'string', description: 'ServiceNow encoded query or natural language description' },
105
- fields: { type: 'array', items: { type: 'string' }, description: 'Specific fields to return' },
106
- limit: { type: 'number', default: 10, description: 'Maximum number of results (default: 10)' },
107
- include__analysis: { type: 'boolean', default: false, description: 'Include intelligent _analysis of incidents' }
108
- },
109
- required: ['query']
110
- }
111
- },
112
- {
113
- name: 'snow_analyze_incident',
114
- description: 'Intelligent _analysis of a specific incident with auto-resolution suggestions',
115
- inputSchema: {
116
- type: 'object',
117
- properties: {
118
- incident_id: { type: 'string', description: 'Incident number or sys_id' },
119
- include_similar: { type: 'boolean', default: true, description: 'Include similar incidents in _analysis' },
120
- suggest_resolution: { type: 'boolean', default: true, description: 'Generate automated resolution suggestions' }
121
- },
122
- required: ['incident_id']
123
- }
124
- },
125
- {
126
- name: 'snow_auto_resolve_incident',
127
- description: 'Attempt automated resolution of technical incidents',
128
- inputSchema: {
129
- type: 'object',
130
- properties: {
131
- incident_id: { type: 'string', description: 'Incident number or sys_id' },
132
- dry_run: { type: 'boolean', default: true, description: 'Preview actions without executing' }
133
- },
134
- required: ['incident_id']
135
- }
136
- },
137
- {
138
- name: 'snow_query_requests',
139
- description: 'Query and analyze service requests',
140
- inputSchema: {
141
- type: 'object',
142
- properties: {
143
- query: { type: 'string', description: 'ServiceNow encoded query or natural language' },
144
- include_items: { type: 'boolean', default: false, description: 'Include request items' },
145
- limit: { type: 'number', default: 10, description: 'Maximum number of results' }
146
- },
147
- required: ['query']
148
- }
149
- },
150
- {
151
- name: 'snow_query_problems',
152
- description: 'Query and analyze problems with root cause _analysis',
153
- inputSchema: {
154
- type: 'object',
155
- properties: {
156
- query: { type: 'string', description: 'ServiceNow encoded query or natural language' },
157
- include_incidents: { type: 'boolean', default: false, description: 'Include related incidents' },
158
- limit: { type: 'number', default: 10, description: 'Maximum number of results' }
159
- },
160
- required: ['query']
161
- }
162
- },
163
- {
164
- name: 'snow_cmdb_search',
165
- description: 'Search and analyze Configuration Items (CMDB)',
166
- inputSchema: {
167
- type: 'object',
168
- properties: {
169
- query: { type: 'string', description: 'Search query for configuration items' },
170
- ci_type: {
171
- type: 'string',
172
- enum: ['server', 'application', 'database', 'network_device', 'service', 'any'],
173
- description: 'Type of CI (server, application, service, etc.)'
174
- },
175
- include_relationships: { type: 'boolean', default: false, description: 'Include CI relationships' },
176
- limit: { type: 'number', default: 10, description: 'Maximum number of results' }
177
- },
178
- required: ['query']
179
- }
180
- },
181
- {
182
- name: 'snow_user_lookup',
183
- description: 'Lookup and analyze user information',
184
- inputSchema: {
185
- type: 'object',
186
- properties: {
187
- identifier: { type: 'string', description: 'User ID, email, or name' },
188
- include_groups: { type: 'boolean', default: true, description: 'Include user groups' },
189
- include_roles: { type: 'boolean', default: true, description: 'Include user roles' }
190
- },
191
- required: ['identifier']
192
- }
193
- },
194
- {
195
- name: 'snow_operational_metrics',
196
- description: 'Get operational metrics and analytics',
197
- inputSchema: {
198
- type: 'object',
199
- properties: {
200
- timeframe: {
201
- type: 'string',
202
- enum: ['today', 'week', 'month', 'quarter'],
203
- default: 'week',
204
- description: 'Time period for metrics'
205
- },
206
- metric_types: { type: 'array', items: { type: 'string' }, description: 'Types of metrics to include' }
207
- }
208
- }
209
- },
210
- {
211
- name: 'snow_pattern__analysis',
212
- description: 'Analyze patterns in incidents, requests, and problems',
213
- inputSchema: {
214
- type: 'object',
215
- properties: {
216
- analysis_type: {
217
- type: 'string',
218
- enum: ['incident_patterns', 'request_trends', 'problem_root_causes', 'user_behavior'],
219
- description: 'Type of pattern _analysis'
220
- },
221
- timeframe: {
222
- type: 'string',
223
- enum: ['day', 'week', 'month', 'quarter'],
224
- default: 'week',
225
- description: 'Time period for _analysis'
226
- }
227
- },
228
- required: ['analysis_type']
229
- }
230
- },
231
- {
232
- name: 'snow_knowledge_search',
233
- description: 'Search knowledge base articles with intelligent matching',
234
- inputSchema: {
235
- type: 'object',
236
- properties: {
237
- query: { type: 'string', description: 'Search query or incident description' },
238
- match_incident: { type: 'string', description: 'Match knowledge to specific incident' },
239
- limit: { type: 'number', default: 5, description: 'Maximum number of results' }
240
- },
241
- required: ['query']
242
- }
243
- },
244
- {
245
- name: 'snow_predictive__analysis',
246
- description: 'Predictive _analysis for potential issues and trends',
247
- inputSchema: {
248
- type: 'object',
249
- properties: {
250
- prediction_type: {
251
- type: 'string',
252
- enum: ['incident_volume', 'system_failure', 'resource_exhaustion', 'user_impact'],
253
- description: 'Type of prediction'
254
- },
255
- timeframe: {
256
- type: 'string',
257
- enum: ['day', 'week', 'month'],
258
- default: 'week',
259
- description: 'Prediction timeframe'
260
- }
261
- },
262
- required: ['prediction_type']
263
- }
264
- },
265
- {
266
- name: 'snow_catalog_item_manager',
267
- description: 'Manage service catalog items - create, update, configure variables and workflows',
268
- inputSchema: {
269
- type: 'object',
270
- properties: {
271
- action: {
272
- type: 'string',
273
- enum: ['create', 'update', 'list', 'get', 'add_variable', 'set_workflow', 'publish', 'retire'],
274
- description: 'Action to perform'
275
- },
276
- item_id: { type: 'string', description: 'Catalog item sys_id (for update/get actions)' },
277
- name: { type: 'string', description: 'Catalog item name' },
278
- short_description: { type: 'string', description: 'Short description' },
279
- description: { type: 'string', description: 'Full description' },
280
- category_id: { type: 'string', description: 'Category sys_id' },
281
- price: { type: 'string', description: 'Item price (e.g., "100.00")' },
282
- recurring_price: { type: 'string', description: 'Recurring price if applicable' },
283
- active: { type: 'boolean', default: true, description: 'Whether the item is active' },
284
- variables: {
285
- type: 'array',
286
- items: {
287
- type: 'object',
288
- properties: {
289
- name: { type: 'string' },
290
- label: { type: 'string' },
291
- type: {
292
- type: 'string',
293
- enum: ['single_line_text', 'multi_line_text', 'select_box', 'checkbox', 'reference', 'date', 'datetime']
294
- },
295
- mandatory: { type: 'boolean' },
296
- default_value: { type: 'string' },
297
- choices: { type: 'array', items: { type: 'string' } }
298
- }
299
- },
300
- description: 'Variables to add'
301
- }
302
- },
303
- required: ['action']
304
- }
305
- },
306
- {
307
- name: 'snow_catalog_item_search',
308
- description: 'Search for catalog items with intelligent matching and discovery',
309
- inputSchema: {
310
- type: 'object',
311
- properties: {
312
- query: { type: 'string', description: 'Search query (e.g., "iPhone", "laptop", "mobile device")' },
313
- category_filter: { type: 'string', description: 'Filter by category name or sys_id' },
314
- include_variables: { type: 'boolean', default: false, description: 'Include catalog item variables in results' },
315
- include_inactive: { type: 'boolean', default: false, description: 'Include inactive catalog items' },
316
- fuzzy_match: { type: 'boolean', default: true, description: 'Enable fuzzy matching for similar items' },
317
- limit: { type: 'number', default: 50, description: 'Maximum results to return' }
318
- },
319
- required: ['query']
320
- }
321
- },
322
- {
323
- name: 'snow_cleanup_test_artifacts',
324
- description: 'Clean up test artifacts while preserving Update Set audit trail',
325
- inputSchema: {
326
- type: 'object',
327
- properties: {
328
- artifact_types: {
329
- type: 'array',
330
- items: {
331
- type: 'string',
332
- enum: ['catalog_items', 'flows', 'users', 'requests', 'all']
333
- },
334
- default: ['catalog_items', 'flows', 'users'],
335
- description: 'Types of artifacts to clean up'
336
- },
337
- dry_run: { type: 'boolean', default: false, description: 'Preview what would be deleted without actually deleting' },
338
- max_age_hours: { type: 'number', default: 1, description: 'Only clean artifacts older than this (hours)' }
339
- }
340
- }
341
- },
342
- {
343
- name: 'snow_create_user_group',
344
- description: 'Create a new user group in ServiceNow',
345
- inputSchema: {
346
- type: 'object',
347
- properties: {
348
- name: { type: 'string', description: 'Group name (e.g., "Need Approval")' },
349
- description: { type: 'string', description: 'Group description' },
350
- email: { type: 'string', description: 'Group email address (optional)' },
351
- manager: { type: 'string', description: 'Group manager sys_id or user_name (optional)' },
352
- parent: { type: 'string', description: 'Parent group sys_id (optional)' },
353
- active: { type: 'boolean', default: true, description: 'Is group active' }
354
- },
355
- required: ['name']
356
- }
357
- },
358
- {
359
- name: 'snow_create_user',
360
- description: 'Create a new user in ServiceNow',
361
- inputSchema: {
362
- type: 'object',
363
- properties: {
364
- user_name: { type: 'string', description: 'Unique username for login' },
365
- first_name: { type: 'string', description: 'User first name' },
366
- last_name: { type: 'string', description: 'User last name' },
367
- email: { type: 'string', description: 'User email address' },
368
- title: { type: 'string', description: 'Job title (optional)' },
369
- department: { type: 'string', description: 'Department name or sys_id (optional)' },
370
- manager: { type: 'string', description: 'Manager sys_id or user_name (optional)' },
371
- phone: { type: 'string', description: 'Phone number (optional)' },
372
- location: { type: 'string', description: 'Location name or sys_id (optional)' },
373
- active: { type: 'boolean', default: true, description: 'Is user active' }
374
- },
375
- required: ['user_name', 'first_name', 'last_name', 'email']
376
- }
377
- },
378
- {
379
- name: 'snow_assign_user_to_group',
380
- description: 'Add a user to a group in ServiceNow',
381
- inputSchema: {
382
- type: 'object',
383
- properties: {
384
- user: { type: 'string', description: 'User sys_id or user_name' },
385
- group: { type: 'string', description: 'Group sys_id or name' }
386
- },
387
- required: ['user', 'group']
388
- }
389
- },
390
- {
391
- name: 'snow_remove_user_from_group',
392
- description: 'Remove a user from a group in ServiceNow',
393
- inputSchema: {
394
- type: 'object',
395
- properties: {
396
- user: { type: 'string', description: 'User sys_id or user_name' },
397
- group: { type: 'string', description: 'Group sys_id or name' }
398
- },
399
- required: ['user', 'group']
400
- }
401
- },
402
- {
403
- name: 'snow_list_group_members',
404
- description: 'List all members of a group',
405
- inputSchema: {
406
- type: 'object',
407
- properties: {
408
- group: { type: 'string', description: 'Group sys_id or name' },
409
- active_only: { type: 'boolean', default: true, description: 'Only show active users' }
410
- },
411
- required: ['group']
412
- }
413
- }
414
- ];
415
- }
416
-
417
- protected async executeTool(name: string, args: any): Promise<ToolResult> {
418
- const startTime = Date.now();
419
-
420
- try {
421
- switch (name) {
422
- case 'snow_query_incidents':
423
- return await this.handleQueryIncidents(args);
424
- case 'snow_analyze_incident':
425
- return await this.handleAnalyzeIncident(args);
426
- case 'snow_auto_resolve_incident':
427
- return await this.handleAutoResolveIncident(args);
428
- case 'snow_query_requests':
429
- return await this.handleQueryRequests(args);
430
- case 'snow_query_problems':
431
- return await this.handleQueryProblems(args);
432
- case 'snow_cmdb_search':
433
- return await this.handleCmdbSearch(args);
434
- case 'snow_user_lookup':
435
- return await this.handleUserLookup(args);
436
- case 'snow_operational_metrics':
437
- return await this.handleOperationalMetrics(args);
438
- case 'snow_pattern__analysis':
439
- return await this.handlePatternAnalysis(args);
440
- case 'snow_knowledge_search':
441
- return await this.handleKnowledgeSearch(args);
442
- case 'snow_predictive__analysis':
443
- return await this.handlePredictiveAnalysis(args);
444
- case 'snow_catalog_item_manager':
445
- return await this.handleCatalogItemManager(args);
446
- case 'snow_catalog_item_search':
447
- return await this.handleCatalogItemSearch(args);
448
- case 'snow_cleanup_test_artifacts':
449
- return await this.handleCleanupTestArtifacts(args);
450
- case 'snow_create_user_group':
451
- return await this.handleCreateUserGroup(args);
452
- case 'snow_create_user':
453
- return await this.handleCreateUser(args);
454
- case 'snow_assign_user_to_group':
455
- return await this.handleAssignUserToGroup(args);
456
- case 'snow_remove_user_from_group':
457
- return await this.handleRemoveUserFromGroup(args);
458
- case 'snow_list_group_members':
459
- return await this.handleListGroupMembers(args);
460
- default:
461
- return {
462
- success: false,
463
- error: `Unknown tool: ${name}`
464
- };
465
- }
466
- } catch (error) {
467
- this.logger.error(`Tool execution failed: ${name}`, error);
468
- return {
469
- success: false,
470
- error: error instanceof Error ? error.message : 'Tool execution failed',
471
- executionTime: Date.now() - startTime
472
- };
473
- }
474
- }
475
-
476
- // Tool implementations
477
-
478
- private async handleQueryIncidents(args: any): Promise<ToolResult> {
479
- const { query, fields, limit = 10, include__analysis } = args;
480
-
481
- const queryParams: any = {
482
- sysparm_query: this.parseQuery(query),
483
- sysparm_limit: limit
484
- };
485
-
486
- if (fields && fields.length > 0) {
487
- queryParams.sysparm_fields = fields.join(',');
488
- }
489
-
490
- const response = await this.client.makeRequest({
491
- method: 'GET',
492
- url: '/api/now/table/incident',
493
- params: queryParams
494
- });
495
-
496
- if (!response.success) {
497
- return {
498
- success: false,
499
- error: response.error || 'Failed to query incidents'
500
- };
501
- }
502
-
503
- let result = {
504
- incidents: response.result,
505
- total: response.result.length
506
- };
507
-
508
- if (include__analysis && response.result.length > 0) {
509
- // Add basic analysis
510
- const _analysis = this.analyzeIncidentPatterns(response.result);
511
- result = { ...result, ..._analysis };
512
- }
513
-
514
- return {
515
- success: true,
516
- result
517
- };
518
- }
519
-
520
- private async handleAnalyzeIncident(args: any): Promise<ToolResult> {
521
- const { incident_id, include_similar, suggest_resolution } = args;
522
-
523
- // Get incident details
524
- const response = await this.client.makeRequest({
525
- method: 'GET',
526
- url: `/api/now/table/incident/${incident_id}`
527
- });
528
-
529
- if (!response.success || !response.result) {
530
- return {
531
- success: false,
532
- error: 'Incident not found'
533
- };
534
- }
535
-
536
- const incident = response.result;
537
- const _analysis: IncidentAnalysis = {
538
- incident_id: incident.sys_id,
539
- patterns_found: this.detectPatterns(incident.short_description + ' ' + incident.description),
540
- root_cause__analysis: 'Automated _analysis based on patterns',
541
- suggested_resolution: [],
542
- confidence_score: 0.75,
543
- similar_incidents: [],
544
- knowledge_articles: [],
545
- automated_actions: []
546
- };
547
-
548
- if (include_similar) {
549
- // Find similar incidents
550
- const similarQuery = this.buildSimilarQuery(incident);
551
- const similarResponse = await this.client.makeRequest({
552
- method: 'GET',
553
- url: '/api/now/table/incident',
554
- params: {
555
- sysparm_query: similarQuery,
556
- sysparm_limit: 5
557
- }
558
- });
559
-
560
- if (similarResponse.success) {
561
- _analysis.similar_incidents = similarResponse.result;
562
- }
563
- }
564
-
565
- if (suggest_resolution) {
566
- _analysis.suggested_resolution = this.generateResolutionSuggestions(incident, _analysis.patterns_found);
567
- }
568
-
569
- return {
570
- success: true,
571
- result: _analysis
572
- };
573
- }
574
-
575
- private async handleAutoResolveIncident(args: any): Promise<ToolResult> {
576
- const { incident_id, dry_run = true } = args;
577
-
578
- // Get incident details
579
- const response = await this.client.makeRequest({
580
- method: 'GET',
581
- url: `/api/now/table/incident/${incident_id}`
582
- });
583
-
584
- if (!response.success || !response.result) {
585
- return {
586
- success: false,
587
- error: 'Incident not found'
588
- };
589
- }
590
-
591
- const incident = response.result;
592
- const patterns = this.detectPatterns(incident.short_description + ' ' + incident.description);
593
- const actions = this.determineAutomatedActions(patterns);
594
-
595
- if (dry_run) {
596
- return {
597
- success: true,
598
- result: {
599
- incident_id,
600
- proposed_actions: actions,
601
- dry_run: true,
602
- message: 'These actions would be performed in a real run'
603
- }
604
- };
605
- }
606
-
607
- // Execute actions (simplified)
608
- const executedActions = [];
609
- for (const action of actions) {
610
- executedActions.push({
611
- action: action,
612
- status: 'would_execute',
613
- timestamp: new Date().toISOString()
614
- });
615
- }
616
-
617
- return {
618
- success: true,
619
- result: {
620
- incident_id,
621
- executed_actions: executedActions,
622
- dry_run: false,
623
- resolution_notes: 'Automated resolution attempted'
624
- }
625
- };
626
- }
627
-
628
- private async handleQueryRequests(args: any): Promise<ToolResult> {
629
- const { query, include_items, limit = 10 } = args;
630
-
631
- const queryParams: any = {
632
- sysparm_query: this.parseQuery(query),
633
- sysparm_limit: limit
634
- };
635
-
636
- const response = await this.client.makeRequest({
637
- method: 'GET',
638
- url: '/api/now/table/sc_request',
639
- params: queryParams
640
- });
641
-
642
- if (!response.success) {
643
- return {
644
- success: false,
645
- error: response.error || 'Failed to query requests'
646
- };
647
- }
648
-
649
- const result = {
650
- requests: response.result,
651
- total: response.result.length
652
- };
653
-
654
- if (include_items && response.result.length > 0) {
655
- // Get request items for each request
656
- for (const request of response.result) {
657
- const itemsResponse = await this.client.makeRequest({
658
- method: 'GET',
659
- url: '/api/now/table/sc_req_item',
660
- params: {
661
- sysparm_query: `request=${request.sys_id}`,
662
- sysparm_limit: 10
663
- }
664
- });
665
-
666
- if (itemsResponse.success) {
667
- request.items = itemsResponse.result;
668
- }
669
- }
670
- }
671
-
672
- return {
673
- success: true,
674
- result
675
- };
676
- }
677
-
678
- private async handleQueryProblems(args: any): Promise<ToolResult> {
679
- const { query, include_incidents, limit = 10 } = args;
680
-
681
- const queryParams: any = {
682
- sysparm_query: this.parseQuery(query),
683
- sysparm_limit: limit
684
- };
685
-
686
- const response = await this.client.makeRequest({
687
- method: 'GET',
688
- url: '/api/now/table/problem',
689
- params: queryParams
690
- });
691
-
692
- if (!response.success) {
693
- return {
694
- success: false,
695
- error: response.error || 'Failed to query problems'
696
- };
697
- }
698
-
699
- const result = {
700
- problems: response.result,
701
- total: response.result.length
702
- };
703
-
704
- if (include_incidents && response.result.length > 0) {
705
- // Get related incidents for each problem
706
- for (const problem of response.result) {
707
- const incidentsResponse = await this.client.makeRequest({
708
- method: 'GET',
709
- url: '/api/now/table/incident',
710
- params: {
711
- sysparm_query: `problem_id=${problem.sys_id}`,
712
- sysparm_limit: 10
713
- }
714
- });
715
-
716
- if (incidentsResponse.success) {
717
- problem.related_incidents = incidentsResponse.result;
718
- }
719
- }
720
- }
721
-
722
- return {
723
- success: true,
724
- result
725
- };
726
- }
727
-
728
- private async handleCmdbSearch(args: any): Promise<ToolResult> {
729
- const { query, ci_type, include_relationships, limit = 10 } = args;
730
-
731
- let table = 'cmdb_ci';
732
- if (ci_type && ci_type !== 'any') {
733
- table = operationalTableMapping[ci_type] || `cmdb_ci_${ci_type}`;
734
- }
735
-
736
- const queryParams: any = {
737
- sysparm_query: this.parseQuery(query),
738
- sysparm_limit: limit
739
- };
740
-
741
- const response = await this.client.makeRequest({
742
- method: 'GET',
743
- url: `/api/now/table/${table}`,
744
- params: queryParams
745
- });
746
-
747
- if (!response.success) {
748
- return {
749
- success: false,
750
- error: response.error || 'Failed to search CMDB'
751
- };
752
- }
753
-
754
- const result = {
755
- configuration_items: response.result,
756
- total: response.result.length,
757
- ci_type: ci_type || 'any'
758
- };
759
-
760
- if (include_relationships && response.result.length > 0) {
761
- // Get relationships for each CI
762
- for (const ci of response.result) {
763
- const relResponse = await this.client.makeRequest({
764
- method: 'GET',
765
- url: '/api/now/table/cmdb_rel_ci',
766
- params: {
767
- sysparm_query: `parent=${ci.sys_id}^ORchild=${ci.sys_id}`,
768
- sysparm_limit: 10
769
- }
770
- });
771
-
772
- if (relResponse.success) {
773
- ci.relationships = relResponse.result;
774
- }
775
- }
776
- }
777
-
778
- return {
779
- success: true,
780
- result
781
- };
782
- }
783
-
784
- private async handleUserLookup(args: any): Promise<ToolResult> {
785
- const { identifier, include_groups, include_roles } = args;
786
-
787
- // Build query based on identifier type
788
- let query = '';
789
- if (identifier.includes('@')) {
790
- query = `email=${identifier}`;
791
- } else if (identifier.match(/^[a-f0-9]{32}$/)) {
792
- query = `sys_id=${identifier}`;
793
- } else {
794
- query = `user_name=${identifier}^ORname=${identifier}`;
795
- }
796
-
797
- const response = await this.client.makeRequest({
798
- method: 'GET',
799
- url: '/api/now/table/sys_user',
800
- params: {
801
- sysparm_query: query,
802
- sysparm_limit: 1
803
- }
804
- });
805
-
806
- if (!response.success || response.result.length === 0) {
807
- return {
808
- success: false,
809
- error: 'User not found'
810
- };
811
- }
812
-
813
- const user = response.result[0];
814
- const result: any = { user };
815
-
816
- if (include_groups) {
817
- const groupsResponse = await this.client.makeRequest({
818
- method: 'GET',
819
- url: '/api/now/table/sys_user_grmember',
820
- params: {
821
- sysparm_query: `user=${user.sys_id}`,
822
- sysparm_fields: 'group.name,group.sys_id'
823
- }
824
- });
825
-
826
- if (groupsResponse.success) {
827
- result.groups = groupsResponse.result.map((g: any) => g.group);
828
- }
829
- }
830
-
831
- if (include_roles) {
832
- const rolesResponse = await this.client.makeRequest({
833
- method: 'GET',
834
- url: '/api/now/table/sys_user_has_role',
835
- params: {
836
- sysparm_query: `user=${user.sys_id}`,
837
- sysparm_fields: 'role.name,role.sys_id'
838
- }
839
- });
840
-
841
- if (rolesResponse.success) {
842
- result.roles = rolesResponse.result.map((r: any) => r.role);
843
- }
844
- }
845
-
846
- return {
847
- success: true,
848
- result
849
- };
850
- }
851
-
852
- private async handleOperationalMetrics(args: any): Promise<ToolResult> {
853
- const { timeframe = 'week', metric_types } = args;
854
-
855
- // Calculate date range
856
- const endDate = new Date();
857
- const startDate = new Date();
858
-
859
- switch (timeframe) {
860
- case 'today':
861
- startDate.setHours(0, 0, 0, 0);
862
- break;
863
- case 'week':
864
- startDate.setDate(startDate.getDate() - 7);
865
- break;
866
- case 'month':
867
- startDate.setMonth(startDate.getMonth() - 1);
868
- break;
869
- case 'quarter':
870
- startDate.setMonth(startDate.getMonth() - 3);
871
- break;
872
- }
873
-
874
- const dateQuery = `sys_created_on>=${startDate.toISOString()}^sys_created_on<=${endDate.toISOString()}`;
875
-
876
- // Get incident metrics
877
- const incidentResponse = await this.client.makeRequest({
878
- method: 'GET',
879
- url: '/api/now/stats/incident',
880
- params: {
881
- sysparm_query: dateQuery,
882
- sysparm_group_by: 'state,priority,category',
883
- sysparm_count: true
884
- }
885
- });
886
-
887
- const metrics: any = {
888
- timeframe,
889
- period: {
890
- start: startDate.toISOString(),
891
- end: endDate.toISOString()
892
- },
893
- incidents: {}
894
- };
895
-
896
- if (incidentResponse.success) {
897
- metrics.incidents = this.processIncidentMetrics(incidentResponse.result);
898
- }
899
-
900
- // Add more metrics based on metric_types if specified
901
- if (metric_types && metric_types.includes('requests')) {
902
- const requestResponse = await this.client.makeRequest({
903
- method: 'GET',
904
- url: '/api/now/stats/sc_request',
905
- params: {
906
- sysparm_query: dateQuery,
907
- sysparm_count: true
908
- }
909
- });
910
-
911
- if (requestResponse.success) {
912
- metrics.requests = {
913
- total: requestResponse.result.length || 0
914
- };
915
- }
916
- }
917
-
918
- return {
919
- success: true,
920
- result: metrics
921
- };
922
- }
923
-
924
- private async handlePatternAnalysis(args: any): Promise<ToolResult> {
925
- const { analysis_type, timeframe = 'week' } = args;
926
-
927
- // This would normally do sophisticated pattern analysis
928
- // For now, return a simplified analysis
929
- const patterns = {
930
- analysis_type,
931
- timeframe,
932
- patterns_detected: [],
933
- insights: [],
934
- recommendations: []
935
- };
936
-
937
- switch (analysis_type) {
938
- case 'incident_patterns':
939
- patterns.patterns_detected = [
940
- 'Increased network-related incidents on Monday mornings',
941
- 'Database timeout issues correlate with backup schedules',
942
- 'User authentication failures spike after password policy changes'
943
- ];
944
- patterns.insights = [
945
- 'Network capacity may be insufficient for Monday morning load',
946
- 'Backup process may be impacting database performance'
947
- ];
948
- patterns.recommendations = [
949
- 'Consider network capacity upgrade',
950
- 'Review backup scheduling and database optimization'
951
- ];
952
- break;
953
-
954
- case 'request_trends':
955
- patterns.patterns_detected = [
956
- 'Mobile device requests increase 40% quarter-over-quarter',
957
- 'Software requests peak at month-end',
958
- 'VPN access requests correlate with remote work announcements'
959
- ];
960
- patterns.insights = [
961
- 'Mobile-first strategy appears to be driving device requests',
962
- 'Budget cycles may be driving month-end software requests'
963
- ];
964
- break;
965
- }
966
-
967
- return {
968
- success: true,
969
- result: patterns
970
- };
971
- }
972
-
973
- private async handleKnowledgeSearch(args: any): Promise<ToolResult> {
974
- const { query, match_incident, limit = 5 } = args;
975
-
976
- let searchQuery = query;
977
-
978
- // If matching to specific incident, get incident details first
979
- if (match_incident) {
980
- const incidentResponse = await this.client.makeRequest({
981
- method: 'GET',
982
- url: `/api/now/table/incident/${match_incident}`,
983
- params: {
984
- sysparm_fields: 'short_description,description,category'
985
- }
986
- });
987
-
988
- if (incidentResponse.success && incidentResponse.result) {
989
- const incident = incidentResponse.result;
990
- searchQuery = `${incident.short_description} ${incident.description} ${incident.category}`;
991
- }
992
- }
993
-
994
- // Search knowledge base
995
- const response = await this.client.makeRequest({
996
- method: 'GET',
997
- url: '/api/now/table/kb_knowledge',
998
- params: {
999
- sysparm_query: `workflow_state=published^short_descriptionLIKE${searchQuery}^ORtextLIKE${searchQuery}`,
1000
- sysparm_limit: limit,
1001
- sysparm_fields: 'number,short_description,wiki,sys_id,kb_category'
1002
- }
1003
- });
1004
-
1005
- if (!response.success) {
1006
- return {
1007
- success: false,
1008
- error: response.error || 'Failed to search knowledge base'
1009
- };
1010
- }
1011
-
1012
- return {
1013
- success: true,
1014
- result: {
1015
- query: searchQuery,
1016
- articles: response.result,
1017
- total: response.result.length,
1018
- matched_incident: match_incident || null
1019
- }
1020
- };
1021
- }
1022
-
1023
- private async handlePredictiveAnalysis(args: any): Promise<ToolResult> {
1024
- const { prediction_type, timeframe = 'week' } = args;
1025
-
1026
- // Simplified predictive analysis
1027
- const predictions: any = {
1028
- prediction_type,
1029
- timeframe,
1030
- predictions: [],
1031
- confidence: 0.7,
1032
- based_on: 'Historical patterns and current trends'
1033
- };
1034
-
1035
- switch (prediction_type) {
1036
- case 'incident_volume':
1037
- predictions.predictions = [
1038
- {
1039
- metric: 'incident_volume',
1040
- current_rate: '45/day',
1041
- predicted_rate: '52/day',
1042
- change: '+15%',
1043
- factors: ['Seasonal increase', 'New system deployments']
1044
- }
1045
- ];
1046
- break;
1047
-
1048
- case 'system_failure':
1049
- predictions.predictions = [
1050
- {
1051
- system: 'Database Server DB01',
1052
- failure_probability: 0.23,
1053
- timeframe: 'next 7 days',
1054
- indicators: ['Increasing response times', 'Memory usage trending up']
1055
- }
1056
- ];
1057
- break;
1058
- }
1059
-
1060
- return {
1061
- success: true,
1062
- result: predictions
1063
- };
1064
- }
1065
-
1066
- private async handleCatalogItemManager(args: any): Promise<ToolResult> {
1067
- const { action, item_id, ...itemData } = args;
1068
-
1069
- switch (action) {
1070
- case 'create':
1071
- return await this.createCatalogItem(itemData);
1072
- case 'update':
1073
- return await this.updateCatalogItem(item_id, itemData);
1074
- case 'list':
1075
- return await this.listCatalogItems();
1076
- case 'get':
1077
- return await this.getCatalogItem(item_id);
1078
- case 'publish':
1079
- return await this.publishCatalogItem(item_id);
1080
- case 'retire':
1081
- return await this.retireCatalogItem(item_id);
1082
- default:
1083
- return {
1084
- success: false,
1085
- error: `Unknown action: ${action}`
1086
- };
1087
- }
1088
- }
1089
-
1090
- private async handleCatalogItemSearch(args: any): Promise<ToolResult> {
1091
- const { query, category_filter, include_variables, include_inactive, fuzzy_match, limit = 50 } = args;
1092
-
1093
- let searchQuery = `nameLIKE${query}^ORshort_descriptionLIKE${query}`;
1094
-
1095
- if (!include_inactive) {
1096
- searchQuery += '^active=true';
1097
- }
1098
-
1099
- if (category_filter) {
1100
- searchQuery += `^category=${category_filter}`;
1101
- }
1102
-
1103
- const response = await this.client.makeRequest({
1104
- method: 'GET',
1105
- url: '/api/now/table/sc_cat_item',
1106
- params: {
1107
- sysparm_query: searchQuery,
1108
- sysparm_limit: limit
1109
- }
1110
- });
1111
-
1112
- if (!response.success) {
1113
- return {
1114
- success: false,
1115
- error: response.error || 'Failed to search catalog items'
1116
- };
1117
- }
1118
-
1119
- let items = response.result;
1120
-
1121
- // Apply fuzzy matching if enabled
1122
- if (fuzzy_match && items.length === 0) {
1123
- // Try alternative searches
1124
- const fuzzyQueries = this.generateFuzzyQueries(query);
1125
- for (const fuzzyQuery of fuzzyQueries) {
1126
- const fuzzyResponse = await this.client.makeRequest({
1127
- method: 'GET',
1128
- url: '/api/now/table/sc_cat_item',
1129
- params: {
1130
- sysparm_query: `nameLIKE${fuzzyQuery}^ORshort_descriptionLIKE${fuzzyQuery}`,
1131
- sysparm_limit: limit
1132
- }
1133
- });
1134
-
1135
- if (fuzzyResponse.success && fuzzyResponse.result.length > 0) {
1136
- items = fuzzyResponse.result;
1137
- break;
1138
- }
1139
- }
1140
- }
1141
-
1142
- if (include_variables && items.length > 0) {
1143
- // Get variables for each item
1144
- for (const item of items) {
1145
- const varResponse = await this.client.makeRequest({
1146
- method: 'GET',
1147
- url: '/api/now/table/item_option_new',
1148
- params: {
1149
- sysparm_query: `cat_item=${item.sys_id}`,
1150
- sysparm_fields: 'name,question_text,type,order,mandatory'
1151
- }
1152
- });
1153
-
1154
- if (varResponse.success) {
1155
- item.variables = varResponse.result;
1156
- }
1157
- }
1158
- }
1159
-
1160
- return {
1161
- success: true,
1162
- result: {
1163
- catalog_items: items,
1164
- total: items.length,
1165
- query,
1166
- fuzzy_match_used: fuzzy_match && items.length > 0
1167
- }
1168
- };
1169
- } private async handleCleanupTestArtifacts(args: any): Promise<ToolResult> {
1170
- const { artifact_types, dry_run, max_age_hours } = args;
1171
-
1172
- const cutoffTime = new Date();
1173
- cutoffTime.setHours(cutoffTime.getHours() - max_age_hours);
1174
-
1175
- const cleanupResults = {
1176
- dry_run,
1177
- artifacts_found: 0,
1178
- artifacts_deleted: 0,
1179
- by_type: {} as any
1180
- };
1181
-
1182
- for (const type of artifact_types) {
1183
- let table = '';
1184
- let query = '';
1185
-
1186
- switch (type) {
1187
- case 'catalog_items':
1188
- table = 'sc_cat_item';
1189
- query = `nameLIKETest^ORnameLIKEMock^sys_created_on>${cutoffTime.toISOString()}`;
1190
- break;
1191
- case 'flows':
1192
- table = 'sys_hub_flow';
1193
- query = `nameLIKETest^ORnameLIKEMock^sys_created_on>${cutoffTime.toISOString()}`;
1194
- break;
1195
- case 'users':
1196
- table = 'sys_user';
1197
- query = `user_nameLIKEtest^sys_created_on>${cutoffTime.toISOString()}`;
1198
- break;
1199
- case 'requests':
1200
- table = 'sc_request';
1201
- query = `numberLIKETest^sys_created_on>${cutoffTime.toISOString()}`;
1202
- break;
1203
- }
1204
-
1205
- if (table) {
1206
- const response = await this.client.makeRequest({
1207
- method: 'GET',
1208
- url: `/api/now/table/${table}`,
1209
- params: {
1210
- sysparm_query: query,
1211
- sysparm_fields: 'sys_id,name,number'
1212
- }
1213
- });
1214
-
1215
- if (response.success) {
1216
- cleanupResults.artifacts_found += response.result.length;
1217
- cleanupResults.by_type[type] = response.result.length;
1218
-
1219
- if (!dry_run && response.result.length > 0) {
1220
- // Delete artifacts
1221
- for (const artifact of response.result) {
1222
- try {
1223
- await this.client.makeRequest({
1224
- method: 'DELETE',
1225
- url: `/api/now/table/${table}/${artifact.sys_id}`
1226
- });
1227
- cleanupResults.artifacts_deleted++;
1228
- } catch (error) {
1229
- this.logger.error(`Failed to delete ${type} artifact`, error);
1230
- }
1231
- }
1232
- }
1233
- }
1234
- }
1235
- }
1236
-
1237
- return {
1238
- success: true,
1239
- result: cleanupResults
1240
- };
1241
- }
1242
-
1243
- private async handleCreateUserGroup(args: any): Promise<ToolResult> {
1244
- const groupData = {
1245
- name: args.name,
1246
- description: args.description || '',
1247
- email: args.email || '',
1248
- manager: args.manager || '',
1249
- parent: args.parent || '',
1250
- active: args.active !== false
1251
- };
1252
-
1253
- const response = await this.client.makeRequest({
1254
- method: 'POST',
1255
- url: '/api/now/table/sys_user_group',
1256
- data: groupData
1257
- });
1258
-
1259
- if (!response.success) {
1260
- return {
1261
- success: false,
1262
- error: response.error || 'Failed to create user group'
1263
- };
1264
- }
1265
-
1266
- return {
1267
- success: true,
1268
- result: {
1269
- sys_id: response.result.sys_id,
1270
- name: response.result.name,
1271
- created: true
1272
- }
1273
- };
1274
- }
1275
-
1276
- private async handleCreateUser(args: any): Promise<ToolResult> {
1277
- const userData = {
1278
- user_name: args.user_name,
1279
- first_name: args.first_name,
1280
- last_name: args.last_name,
1281
- email: args.email,
1282
- title: args.title || '',
1283
- department: args.department || '',
1284
- manager: args.manager || '',
1285
- phone: args.phone || '',
1286
- location: args.location || '',
1287
- active: args.active !== false
1288
- };
1289
-
1290
- const response = await this.client.makeRequest({
1291
- method: 'POST',
1292
- url: '/api/now/table/sys_user',
1293
- data: userData
1294
- });
1295
-
1296
- if (!response.success) {
1297
- return {
1298
- success: false,
1299
- error: response.error || 'Failed to create user'
1300
- };
1301
- }
1302
-
1303
- return {
1304
- success: true,
1305
- result: {
1306
- sys_id: response.result.sys_id,
1307
- user_name: response.result.user_name,
1308
- created: true
1309
- }
1310
- };
1311
- }
1312
-
1313
- private async handleAssignUserToGroup(args: any): Promise<ToolResult> {
1314
- const { user, group } = args;
1315
-
1316
- // Get user sys_id
1317
- const userResponse = await this.resolveUserIdentifier(user);
1318
- if (!userResponse.success) {
1319
- return userResponse;
1320
- }
1321
-
1322
- // Get group sys_id
1323
- const groupResponse = await this.resolveGroupIdentifier(group);
1324
- if (!groupResponse.success) {
1325
- return groupResponse;
1326
- }
1327
-
1328
- // Create group membership
1329
- const membershipData = {
1330
- user: userResponse.result.sys_id,
1331
- group: groupResponse.result.sys_id
1332
- };
1333
-
1334
- const response = await this.client.makeRequest({
1335
- method: 'POST',
1336
- url: '/api/now/table/sys_user_grmember',
1337
- data: membershipData
1338
- });
1339
-
1340
- if (!response.success) {
1341
- return {
1342
- success: false,
1343
- error: response.error || 'Failed to add user to group'
1344
- };
1345
- }
1346
-
1347
- return {
1348
- success: true,
1349
- result: {
1350
- user: userResponse.result.user_name,
1351
- group: groupResponse.result.name,
1352
- membership_created: true
1353
- }
1354
- };
1355
- }
1356
-
1357
- private async handleRemoveUserFromGroup(args: any): Promise<ToolResult> {
1358
- const { user, group } = args;
1359
-
1360
- // Get user sys_id
1361
- const userResponse = await this.resolveUserIdentifier(user);
1362
- if (!userResponse.success) {
1363
- return userResponse;
1364
- }
1365
-
1366
- // Get group sys_id
1367
- const groupResponse = await this.resolveGroupIdentifier(group);
1368
- if (!groupResponse.success) {
1369
- return groupResponse;
1370
- }
1371
-
1372
- // Find membership record
1373
- const membershipResponse = await this.client.makeRequest({
1374
- method: 'GET',
1375
- url: '/api/now/table/sys_user_grmember',
1376
- params: {
1377
- sysparm_query: `user=${userResponse.result.sys_id}^group=${groupResponse.result.sys_id}`,
1378
- sysparm_limit: 1
1379
- }
1380
- });
1381
-
1382
- if (!membershipResponse.success || membershipResponse.result.length === 0) {
1383
- return {
1384
- success: false,
1385
- error: 'User is not a member of this group'
1386
- };
1387
- }
1388
-
1389
- // Delete membership
1390
- const deleteResponse = await this.client.makeRequest({
1391
- method: 'DELETE',
1392
- url: `/api/now/table/sys_user_grmember/${membershipResponse.result[0].sys_id}`
1393
- });
1394
-
1395
- if (!deleteResponse.success) {
1396
- return {
1397
- success: false,
1398
- error: deleteResponse.error || 'Failed to remove user from group'
1399
- };
1400
- }
1401
-
1402
- return {
1403
- success: true,
1404
- result: {
1405
- user: userResponse.result.user_name,
1406
- group: groupResponse.result.name,
1407
- membership_removed: true
1408
- }
1409
- };
1410
- }
1411
-
1412
- private async handleListGroupMembers(args: any): Promise<ToolResult> {
1413
- const { group, active_only } = args;
1414
-
1415
- // Get group sys_id
1416
- const groupResponse = await this.resolveGroupIdentifier(group);
1417
- if (!groupResponse.success) {
1418
- return groupResponse;
1419
- }
1420
-
1421
- // Get group members
1422
- let query = `group=${groupResponse.result.sys_id}`;
1423
- if (active_only) {
1424
- query += '^user.active=true';
1425
- }
1426
-
1427
- const response = await this.client.makeRequest({
1428
- method: 'GET',
1429
- url: '/api/now/table/sys_user_grmember',
1430
- params: {
1431
- sysparm_query: query,
1432
- sysparm_fields: 'user.user_name,user.name,user.email,user.active'
1433
- }
1434
- });
1435
-
1436
- if (!response.success) {
1437
- return {
1438
- success: false,
1439
- error: response.error || 'Failed to list group members'
1440
- };
1441
- }
1442
-
1443
- return {
1444
- success: true,
1445
- result: {
1446
- group: groupResponse.result.name,
1447
- members: response.result.map((m: any) => m.user),
1448
- total: response.result.length
1449
- }
1450
- };
1451
- }
1452
-
1453
- // Helper methods
1454
-
1455
- private parseQuery(query: string): string {
1456
- // Simple natural language to encoded query conversion
1457
- // In a real implementation, this would be more sophisticated
1458
-
1459
- // If it's already an encoded query, return as-is
1460
- if (query.includes('=') || query.includes('^')) {
1461
- return query;
1462
- }
1463
-
1464
- // Convert natural language to basic queries
1465
- const lowerQuery = query.toLowerCase();
1466
-
1467
- if (lowerQuery.includes('open')) {
1468
- return 'state=1^ORstate=2';
1469
- }
1470
- if (lowerQuery.includes('critical') || lowerQuery.includes('high priority')) {
1471
- return 'priority=1';
1472
- }
1473
- if (lowerQuery.includes('today')) {
1474
- const today = new Date();
1475
- today.setHours(0, 0, 0, 0);
1476
- return `sys_created_on>=${today.toISOString()}`;
1477
- }
1478
-
1479
- // Default: search in short description
1480
- return `short_descriptionLIKE${query}`;
1481
- }
1482
-
1483
- private detectPatterns(text: string): string[] {
1484
- const patterns: string[] = [];
1485
- const lowerText = text.toLowerCase();
1486
-
1487
- // Check against common patterns
1488
- for (const [patternName, patternData] of Object.entries(commonPatterns)) {
1489
- for (const keyword of (patternData as any).keywords) {
1490
- if (lowerText.includes(keyword)) {
1491
- patterns.push(patternName);
1492
- break;
1493
- }
1494
- }
1495
- }
1496
-
1497
- return patterns;
1498
- }
1499
-
1500
- private buildSimilarQuery(incident: any): string {
1501
- // Build query to find similar incidents
1502
- const terms = [];
1503
-
1504
- if (incident.category) {
1505
- terms.push(`category=${incident.category}`);
1506
- }
1507
-
1508
- if (incident.subcategory) {
1509
- terms.push(`subcategory=${incident.subcategory}`);
1510
- }
1511
-
1512
- // Extract keywords from short description
1513
- const keywords = incident.short_description.split(' ')
1514
- .filter((word: string) => word.length > 3)
1515
- .slice(0, 3);
1516
-
1517
- if (keywords.length > 0) {
1518
- terms.push(`short_descriptionLIKE${keywords.join(' ')}`);
1519
- }
1520
-
1521
- return terms.join('^');
1522
- }
1523
-
1524
- private generateResolutionSuggestions(incident: any, patterns: string[]): string[] {
1525
- const suggestions: string[] = [];
1526
-
1527
- // Add suggestions based on patterns
1528
- for (const pattern of patterns) {
1529
- const patternData = (commonPatterns as any)[pattern];
1530
- if (patternData && patternData.common_solutions) {
1531
- suggestions.push(...patternData.common_solutions);
1532
- }
1533
- }
1534
-
1535
- // Add generic suggestions based on incident properties
1536
- if (incident.priority === '1') {
1537
- suggestions.push('Escalate to senior support team');
1538
- suggestions.push('Consider emergency change if needed');
1539
- }
1540
-
1541
- return [...new Set(suggestions)]; // Remove duplicates
1542
- }
1543
-
1544
- private determineAutomatedActions(patterns: string[]): string[] {
1545
- const actions: string[] = [];
1546
-
1547
- if (patterns.includes('network_issues')) {
1548
- actions.push('Run network diagnostic script');
1549
- actions.push('Check network device status');
1550
- }
1551
-
1552
- if (patterns.includes('database_issues')) {
1553
- actions.push('Check database connection pool');
1554
- actions.push('Run database performance _analysis');
1555
- }
1556
-
1557
- if (patterns.includes('auth_issues')) {
1558
- actions.push('Verify LDAP connectivity');
1559
- actions.push('Check user account status');
1560
- }
1561
-
1562
- return actions;
1563
- }
1564
-
1565
- private analyzeIncidentPatterns(incidents: any[]): any {
1566
- const _analysis: any = {
1567
- common_categories: {},
1568
- priority_distribution: {},
1569
- state_distribution: {},
1570
- avg_age_hours: 0
1571
- };
1572
-
1573
- let totalAge = 0;
1574
-
1575
- for (const incident of incidents) {
1576
- // Category analysis
1577
- const category = incident.category || 'uncategorized';
1578
- _analysis.common_categories[category] = (_analysis.common_categories[category] || 0) + 1;
1579
-
1580
- // Priority analysis
1581
- const priority = incident.priority || 'unset';
1582
- _analysis.priority_distribution[priority] = (_analysis.priority_distribution[priority] || 0) + 1;
1583
-
1584
- // State analysis
1585
- const state = incident.state || 'unknown';
1586
- _analysis.state_distribution[state] = (_analysis.state_distribution[state] || 0) + 1;
1587
-
1588
- // Age calculation
1589
- if (incident.sys_created_on) {
1590
- const created = new Date(incident.sys_created_on);
1591
- const age = Date.now() - created.getTime();
1592
- totalAge += age;
1593
- }
1594
- }
1595
-
1596
- if (incidents.length > 0) {
1597
- _analysis.avg_age_hours = Math.round(totalAge / incidents.length / (1000 * 60 * 60));
1598
- }
1599
-
1600
- return { _analysis };
1601
- }
1602
-
1603
- private processIncidentMetrics(data: any): any {
1604
- // Process raw metrics data into useful format
1605
- return {
1606
- total: data.length,
1607
- by_state: this.groupBy(data, 'state'),
1608
- by_priority: this.groupBy(data, 'priority'),
1609
- by_category: this.groupBy(data, 'category')
1610
- };
1611
- }
1612
-
1613
- private groupBy(data: any[], field: string): any {
1614
- return data.reduce((acc, item) => {
1615
- const key = item[field] || 'unknown';
1616
- acc[key] = (acc[key] || 0) + 1;
1617
- return acc;
1618
- }, {});
1619
- }
1620
-
1621
- private generateFuzzyQueries(query: string): string[] {
1622
- const queries: string[] = [];
1623
-
1624
- // Common variations
1625
- if (query.toLowerCase().includes('iphone')) {
1626
- queries.push('iPhone', 'Apple iPhone', 'iOS device', 'mobile phone');
1627
- } else if (query.toLowerCase().includes('laptop')) {
1628
- queries.push('notebook', 'portable computer', 'MacBook', 'ThinkPad');
1629
- } else if (query.toLowerCase().includes('software')) {
1630
- queries.push('application', 'program', 'license');
1631
- }
1632
-
1633
- // Generic variations
1634
- queries.push(query.replace(/\s+/g, '%')); // Replace spaces with wildcards
1635
- queries.push(query.split(' ')[0]); // First word only
1636
-
1637
- return queries;
1638
- }
1639
-
1640
- private async createTestUser(): Promise<any> {
1641
- const testUserData = {
1642
- user_name: `test_user_${Date.now()}`,
1643
- first_name: 'Test',
1644
- last_name: 'User',
1645
- email: `test${Date.now()}@example.com`,
1646
- active: true
1647
- };
1648
-
1649
- const response = await this.client.makeRequest({
1650
- method: 'POST',
1651
- url: '/api/now/table/sys_user',
1652
- data: testUserData
1653
- });
1654
-
1655
- if (!response.success) {
1656
- throw new Error('Failed to create test user');
1657
- }
1658
-
1659
- return response.result;
1660
- }
1661
-
1662
- private async createMockCatalogItems(): Promise<any[]> {
1663
- const mockItems = [
1664
- {
1665
- name: `Mock iPhone ${Date.now()}`,
1666
- short_description: 'Test iPhone for flow testing',
1667
- category: 'hardware',
1668
- price: '999.00'
1669
- },
1670
- {
1671
- name: `Mock Software ${Date.now()}`,
1672
- short_description: 'Test software license',
1673
- category: 'software',
1674
- price: '299.00'
1675
- }
1676
- ];
1677
-
1678
- const created = [];
1679
-
1680
- for (const item of mockItems) {
1681
- const response = await this.client.makeRequest({
1682
- method: 'POST',
1683
- url: '/api/now/table/sc_cat_item',
1684
- data: item
1685
- });
1686
-
1687
- if (response.success) {
1688
- created.push({
1689
- type: 'catalog_item',
1690
- sys_id: response.result.sys_id,
1691
- name: response.result.name
1692
- });
1693
- }
1694
- }
1695
-
1696
- return created;
1697
- }
1698
-
1699
- private async cleanupTestData(testData: any[]): Promise<void> {
1700
- for (const item of testData) {
1701
- let table = '';
1702
-
1703
- switch (item.type) {
1704
- case 'user':
1705
- table = 'sys_user';
1706
- break;
1707
- case 'catalog_item':
1708
- table = 'sc_cat_item';
1709
- break;
1710
- }
1711
-
1712
- if (table) {
1713
- try {
1714
- await this.client.makeRequest({
1715
- method: 'DELETE',
1716
- url: `/api/now/table/${table}/${item.sys_id}`
1717
- });
1718
- } catch (error) {
1719
- this.logger.error(`Failed to cleanup ${item.type}`, error);
1720
- }
1721
- }
1722
- }
1723
- }
1724
-
1725
- private async createCatalogItem(itemData: any): Promise<ToolResult> {
1726
- const catalogItemData = {
1727
- name: itemData.name,
1728
- short_description: itemData.short_description,
1729
- description: itemData.description || '',
1730
- category: itemData.category_id || '',
1731
- price: itemData.price || '0',
1732
- recurring_price: itemData.recurring_price || '',
1733
- active: itemData.active !== false
1734
- };
1735
-
1736
- const response = await this.client.makeRequest({
1737
- method: 'POST',
1738
- url: '/api/now/table/sc_cat_item',
1739
- data: catalogItemData
1740
- });
1741
-
1742
- if (!response.success) {
1743
- return {
1744
- success: false,
1745
- error: response.error || 'Failed to create catalog item'
1746
- };
1747
- }
1748
-
1749
- // Add variables if provided
1750
- if (itemData.variables && itemData.variables.length > 0) {
1751
- await this.addVariablesToCatalogItem(response.result.sys_id, itemData.variables);
1752
- }
1753
-
1754
- return {
1755
- success: true,
1756
- result: {
1757
- sys_id: response.result.sys_id,
1758
- name: response.result.name,
1759
- created: true
1760
- }
1761
- };
1762
- }
1763
-
1764
- private async updateCatalogItem(itemId: string, itemData: any): Promise<ToolResult> {
1765
- const updateData: any = {};
1766
-
1767
- if (itemData.name) updateData.name = itemData.name;
1768
- if (itemData.short_description) updateData.short_description = itemData.short_description;
1769
- if (itemData.description) updateData.description = itemData.description;
1770
- if (itemData.category_id) updateData.category = itemData.category_id;
1771
- if (itemData.price) updateData.price = itemData.price;
1772
- if (itemData.recurring_price) updateData.recurring_price = itemData.recurring_price;
1773
- if (itemData.active !== undefined) updateData.active = itemData.active;
1774
-
1775
- const response = await this.client.makeRequest({
1776
- method: 'PATCH',
1777
- url: `/api/now/table/sc_cat_item/${itemId}`,
1778
- data: updateData
1779
- });
1780
-
1781
- if (!response.success) {
1782
- return {
1783
- success: false,
1784
- error: response.error || 'Failed to update catalog item'
1785
- };
1786
- }
1787
-
1788
- return {
1789
- success: true,
1790
- result: {
1791
- sys_id: response.result.sys_id,
1792
- updated: true
1793
- }
1794
- };
1795
- }
1796
-
1797
- private async listCatalogItems(): Promise<ToolResult> {
1798
- const response = await this.client.makeRequest({
1799
- method: 'GET',
1800
- url: '/api/now/table/sc_cat_item',
1801
- params: {
1802
- sysparm_limit: 100,
1803
- sysparm_fields: 'sys_id,name,short_description,category,active,price'
1804
- }
1805
- });
1806
-
1807
- if (!response.success) {
1808
- return {
1809
- success: false,
1810
- error: response.error || 'Failed to list catalog items'
1811
- };
1812
- }
1813
-
1814
- return {
1815
- success: true,
1816
- result: {
1817
- catalog_items: response.result,
1818
- total: response.result.length
1819
- }
1820
- };
1821
- }
1822
-
1823
- private async getCatalogItem(itemId: string): Promise<ToolResult> {
1824
- const response = await this.client.makeRequest({
1825
- method: 'GET',
1826
- url: `/api/now/table/sc_cat_item/${itemId}`
1827
- });
1828
-
1829
- if (!response.success || !response.result) {
1830
- return {
1831
- success: false,
1832
- error: 'Catalog item not found'
1833
- };
1834
- }
1835
-
1836
- // Get variables
1837
- const varResponse = await this.client.makeRequest({
1838
- method: 'GET',
1839
- url: '/api/now/table/item_option_new',
1840
- params: {
1841
- sysparm_query: `cat_item=${itemId}`,
1842
- sysparm_fields: 'name,question_text,type,order,mandatory'
1843
- }
1844
- });
1845
-
1846
- if (varResponse.success) {
1847
- response.result.variables = varResponse.result;
1848
- }
1849
-
1850
- return {
1851
- success: true,
1852
- result: response.result
1853
- };
1854
- }
1855
-
1856
- private async publishCatalogItem(itemId: string): Promise<ToolResult> {
1857
- return await this.updateCatalogItem(itemId, { active: true });
1858
- }
1859
-
1860
- private async retireCatalogItem(itemId: string): Promise<ToolResult> {
1861
- return await this.updateCatalogItem(itemId, { active: false });
1862
- }
1863
-
1864
- private async addVariablesToCatalogItem(itemId: string, variables: any[]): Promise<void> {
1865
- for (const variable of variables) {
1866
- const varData = {
1867
- cat_item: itemId,
1868
- name: variable.name,
1869
- question_text: variable.label,
1870
- type: variable.type,
1871
- mandatory: variable.mandatory || false,
1872
- default_value: variable.default_value || '',
1873
- order: variable.order || 100
1874
- };
1875
-
1876
- try {
1877
- await this.client.makeRequest({
1878
- method: 'POST',
1879
- url: '/api/now/table/item_option_new',
1880
- data: varData
1881
- });
1882
- } catch (error) {
1883
- this.logger.error(`Failed to add variable ${variable.name}`, error);
1884
- }
1885
- }
1886
- }
1887
-
1888
- private async resolveUserIdentifier(identifier: string): Promise<ToolResult> {
1889
- let query = '';
1890
-
1891
- if (identifier.match(/^[a-f0-9]{32}$/)) {
1892
- query = `sys_id=${identifier}`;
1893
- } else {
1894
- query = `user_name=${identifier}`;
1895
- }
1896
-
1897
- const response = await this.client.makeRequest({
1898
- method: 'GET',
1899
- url: '/api/now/table/sys_user',
1900
- params: {
1901
- sysparm_query: query,
1902
- sysparm_limit: 1
1903
- }
1904
- });
1905
-
1906
- if (!response.success || response.result.length === 0) {
1907
- return {
1908
- success: false,
1909
- error: 'User not found'
1910
- };
1911
- }
1912
-
1913
- return {
1914
- success: true,
1915
- result: response.result[0]
1916
- };
1917
- }
1918
-
1919
- private async resolveGroupIdentifier(identifier: string): Promise<ToolResult> {
1920
- let query = '';
1921
-
1922
- if (identifier.match(/^[a-f0-9]{32}$/)) {
1923
- query = `sys_id=${identifier}`;
1924
- } else {
1925
- query = `name=${identifier}`;
1926
- }
1927
-
1928
- const response = await this.client.makeRequest({
1929
- method: 'GET',
1930
- url: '/api/now/table/sys_user_group',
1931
- params: {
1932
- sysparm_query: query,
1933
- sysparm_limit: 1
1934
- }
1935
- });
1936
-
1937
- if (!response.success || response.result.length === 0) {
1938
- return {
1939
- success: false,
1940
- error: 'Group not found'
1941
- };
1942
- }
1943
-
1944
- return {
1945
- success: true,
1946
- result: response.result[0]
1947
- };
1948
- }
1949
- }
1950
-
1951
- // Simplified common patterns for intelligent _analysis (moved from top to avoid duplication)
1952
- const commonPatterns = {
1953
- network_issues: {
1954
- keywords: ['network', 'connectivity', 'ping', 'dns', 'timeout', 'unreachable'],
1955
- common_solutions: [
1956
- 'Check network connectivity',
1957
- 'Verify DNS resolution',
1958
- 'Test ping to server',
1959
- 'Review firewall rules'
1960
- ]
1961
- },
1962
- database_issues: {
1963
- keywords: ['database', 'connection', 'sql', 'timeout', 'deadlock', 'performance'],
1964
- common_solutions: [
1965
- 'Check database connection',
1966
- 'Review connection pool settings',
1967
- 'Analyze query performance',
1968
- 'Check for blocking processes'
1969
- ]
1970
- },
1971
- application_errors: {
1972
- keywords: ['application', 'error', 'exception', 'crash', 'memory', 'cpu'],
1973
- common_solutions: [
1974
- 'Check application logs',
1975
- 'Review memory usage',
1976
- 'Analyze CPU utilization',
1977
- 'Restart application service'
1978
- ]
1979
- },
1980
- auth_issues: {
1981
- keywords: ['authentication', 'login', 'password', 'ldap', 'sso', 'unauthorized'],
1982
- common_solutions: [
1983
- 'Reset user password',
1984
- 'Check LDAP connectivity',
1985
- 'Verify SSO configuration',
1986
- 'Review user permissions'
1987
- ]
1988
- }
1989
- };
1990
-
1991
- // Create and run the server
1992
- if (require.main === module) {
1993
- const server = new ServiceNowOperationsMCP();
1994
- server.start().catch(console.error);
1995
- }