snow-flow 1.1.0
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/.env.example +49 -0
- package/.mcp.json +106 -0
- package/.mcp.json.template +106 -0
- package/LICENSE +21 -0
- package/README.md +236 -0
- package/bin/snow-flow +4 -0
- package/bin/snow-flow.js +3 -0
- package/claude-flow +79 -0
- package/claude-flow.bat +18 -0
- package/claude-flow.config.json +20 -0
- package/claude-flow.ps1 +24 -0
- package/dist/agents/app-creator.agent.d.ts +55 -0
- package/dist/agents/app-creator.agent.d.ts.map +1 -0
- package/dist/agents/app-creator.agent.js +1292 -0
- package/dist/agents/app-creator.agent.js.map +1 -0
- package/dist/agents/base-snow-agent.d.ts +63 -0
- package/dist/agents/base-snow-agent.d.ts.map +1 -0
- package/dist/agents/base-snow-agent.js +296 -0
- package/dist/agents/base-snow-agent.js.map +1 -0
- package/dist/agents/script-generator.agent.d.ts +32 -0
- package/dist/agents/script-generator.agent.d.ts.map +1 -0
- package/dist/agents/script-generator.agent.js +772 -0
- package/dist/agents/script-generator.agent.js.map +1 -0
- package/dist/agents/ui-builder.agent.d.ts +50 -0
- package/dist/agents/ui-builder.agent.d.ts.map +1 -0
- package/dist/agents/ui-builder.agent.js +1539 -0
- package/dist/agents/ui-builder.agent.js.map +1 -0
- package/dist/agents/widget-builder.agent.d.ts +32 -0
- package/dist/agents/widget-builder.agent.d.ts.map +1 -0
- package/dist/agents/widget-builder.agent.js +439 -0
- package/dist/agents/widget-builder.agent.js.map +1 -0
- package/dist/agents/workflow-designer.agent.d.ts +31 -0
- package/dist/agents/workflow-designer.agent.d.ts.map +1 -0
- package/dist/agents/workflow-designer.agent.js +583 -0
- package/dist/agents/workflow-designer.agent.js.map +1 -0
- package/dist/api/error-handling.d.ts +214 -0
- package/dist/api/error-handling.d.ts.map +1 -0
- package/dist/api/error-handling.js +594 -0
- package/dist/api/error-handling.js.map +1 -0
- package/dist/api/flow-designer-api.d.ts +167 -0
- package/dist/api/flow-designer-api.d.ts.map +1 -0
- package/dist/api/flow-designer-api.js +555 -0
- package/dist/api/flow-designer-api.js.map +1 -0
- package/dist/api/natural-language-mapper.d.ts +126 -0
- package/dist/api/natural-language-mapper.d.ts.map +1 -0
- package/dist/api/natural-language-mapper.js +498 -0
- package/dist/api/natural-language-mapper.js.map +1 -0
- package/dist/api/performance-optimizer.d.ts +240 -0
- package/dist/api/performance-optimizer.d.ts.map +1 -0
- package/dist/api/performance-optimizer.js +701 -0
- package/dist/api/performance-optimizer.js.map +1 -0
- package/dist/api/transaction-manager.d.ts +189 -0
- package/dist/api/transaction-manager.d.ts.map +1 -0
- package/dist/api/transaction-manager.js +576 -0
- package/dist/api/transaction-manager.js.map +1 -0
- package/dist/cli/deploy-artifact.d.ts +7 -0
- package/dist/cli/deploy-artifact.d.ts.map +1 -0
- package/dist/cli/deploy-artifact.js +279 -0
- package/dist/cli/deploy-artifact.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2057 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/managers/scope-manager.d.ts +75 -0
- package/dist/managers/scope-manager.d.ts.map +1 -0
- package/dist/managers/scope-manager.js +448 -0
- package/dist/managers/scope-manager.js.map +1 -0
- package/dist/mcp/mcp-wrapper.d.ts +8 -0
- package/dist/mcp/mcp-wrapper.d.ts.map +1 -0
- package/dist/mcp/mcp-wrapper.js +77 -0
- package/dist/mcp/mcp-wrapper.js.map +1 -0
- package/dist/mcp/servicenow-automation-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-automation-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-automation-mcp.js +683 -0
- package/dist/mcp/servicenow-automation-mcp.js.map +1 -0
- package/dist/mcp/servicenow-deployment-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-deployment-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-deployment-mcp.js +972 -0
- package/dist/mcp/servicenow-deployment-mcp.js.map +1 -0
- package/dist/mcp/servicenow-flow-composer-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-flow-composer-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-flow-composer-mcp.js +1121 -0
- package/dist/mcp/servicenow-flow-composer-mcp.js.map +1 -0
- package/dist/mcp/servicenow-graph-memory-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-graph-memory-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-graph-memory-mcp.js +703 -0
- package/dist/mcp/servicenow-graph-memory-mcp.js.map +1 -0
- package/dist/mcp/servicenow-integration-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-integration-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-integration-mcp.js +689 -0
- package/dist/mcp/servicenow-integration-mcp.js.map +1 -0
- package/dist/mcp/servicenow-intelligent-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-intelligent-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-intelligent-mcp.js +1138 -0
- package/dist/mcp/servicenow-intelligent-mcp.js.map +1 -0
- package/dist/mcp/servicenow-mcp-server.d.ts +37 -0
- package/dist/mcp/servicenow-mcp-server.d.ts.map +1 -0
- package/dist/mcp/servicenow-mcp-server.js +648 -0
- package/dist/mcp/servicenow-mcp-server.js.map +1 -0
- package/dist/mcp/servicenow-operations-mcp.d.ts +15 -0
- package/dist/mcp/servicenow-operations-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-operations-mcp.js +1287 -0
- package/dist/mcp/servicenow-operations-mcp.js.map +1 -0
- package/dist/mcp/servicenow-platform-development-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-platform-development-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-platform-development-mcp.js +557 -0
- package/dist/mcp/servicenow-platform-development-mcp.js.map +1 -0
- package/dist/mcp/servicenow-progressive-indexer.d.ts +79 -0
- package/dist/mcp/servicenow-progressive-indexer.d.ts.map +1 -0
- package/dist/mcp/servicenow-progressive-indexer.js +320 -0
- package/dist/mcp/servicenow-progressive-indexer.js.map +1 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.js +888 -0
- package/dist/mcp/servicenow-reporting-analytics-mcp.js.map +1 -0
- package/dist/mcp/servicenow-security-compliance-mcp.d.ts +8 -0
- package/dist/mcp/servicenow-security-compliance-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-security-compliance-mcp.js +812 -0
- package/dist/mcp/servicenow-security-compliance-mcp.js.map +1 -0
- package/dist/mcp/servicenow-update-set-mcp.d.ts +7 -0
- package/dist/mcp/servicenow-update-set-mcp.d.ts.map +1 -0
- package/dist/mcp/servicenow-update-set-mcp.js +599 -0
- package/dist/mcp/servicenow-update-set-mcp.js.map +1 -0
- package/dist/mcp/start-all-mcp-servers.d.ts +6 -0
- package/dist/mcp/start-all-mcp-servers.d.ts.map +1 -0
- package/dist/mcp/start-all-mcp-servers.js +65 -0
- package/dist/mcp/start-all-mcp-servers.js.map +1 -0
- package/dist/mcp/start-servicenow-mcp.d.ts +7 -0
- package/dist/mcp/start-servicenow-mcp.d.ts.map +1 -0
- package/dist/mcp/start-servicenow-mcp.js +64 -0
- package/dist/mcp/start-servicenow-mcp.js.map +1 -0
- package/dist/mcp/test-simple-mcp.d.ts +6 -0
- package/dist/mcp/test-simple-mcp.d.ts.map +1 -0
- package/dist/mcp/test-simple-mcp.js +64 -0
- package/dist/mcp/test-simple-mcp.js.map +1 -0
- package/dist/orchestrator/flow-composer.d.ts +269 -0
- package/dist/orchestrator/flow-composer.d.ts.map +1 -0
- package/dist/orchestrator/flow-composer.js +2221 -0
- package/dist/orchestrator/flow-composer.js.map +1 -0
- package/dist/orchestrator/flow-pattern-templates.d.ts +260 -0
- package/dist/orchestrator/flow-pattern-templates.d.ts.map +1 -0
- package/dist/orchestrator/flow-pattern-templates.js +906 -0
- package/dist/orchestrator/flow-pattern-templates.js.map +1 -0
- package/dist/orchestrator/flow-subflow-decision-engine.d.ts +202 -0
- package/dist/orchestrator/flow-subflow-decision-engine.d.ts.map +1 -0
- package/dist/orchestrator/flow-subflow-decision-engine.js +769 -0
- package/dist/orchestrator/flow-subflow-decision-engine.js.map +1 -0
- package/dist/orchestrator/flow-validation-engine.d.ts +145 -0
- package/dist/orchestrator/flow-validation-engine.d.ts.map +1 -0
- package/dist/orchestrator/flow-validation-engine.js +663 -0
- package/dist/orchestrator/flow-validation-engine.js.map +1 -0
- package/dist/orchestrator/snow-orchestrator.d.ts +49 -0
- package/dist/orchestrator/snow-orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/snow-orchestrator.js +235 -0
- package/dist/orchestrator/snow-orchestrator.js.map +1 -0
- package/dist/orchestrator/subflow-creation-handler.d.ts +230 -0
- package/dist/orchestrator/subflow-creation-handler.d.ts.map +1 -0
- package/dist/orchestrator/subflow-creation-handler.js +791 -0
- package/dist/orchestrator/subflow-creation-handler.js.map +1 -0
- package/dist/strategies/global-scope-strategy.d.ts +123 -0
- package/dist/strategies/global-scope-strategy.d.ts.map +1 -0
- package/dist/strategies/global-scope-strategy.js +585 -0
- package/dist/strategies/global-scope-strategy.js.map +1 -0
- package/dist/types/index.d.ts +138 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/servicenow.types.d.ts +260 -0
- package/dist/types/servicenow.types.d.ts.map +1 -0
- package/dist/types/servicenow.types.js +3 -0
- package/dist/types/servicenow.types.js.map +1 -0
- package/dist/types/snow-flow.types.d.ts +114 -0
- package/dist/types/snow-flow.types.d.ts.map +1 -0
- package/dist/types/snow-flow.types.js +3 -0
- package/dist/types/snow-flow.types.js.map +1 -0
- package/dist/utils/action-type-cache.d.ts +66 -0
- package/dist/utils/action-type-cache.d.ts.map +1 -0
- package/dist/utils/action-type-cache.js +237 -0
- package/dist/utils/action-type-cache.js.map +1 -0
- package/dist/utils/agent-detector.d.ts +35 -0
- package/dist/utils/agent-detector.d.ts.map +1 -0
- package/dist/utils/agent-detector.js +353 -0
- package/dist/utils/agent-detector.js.map +1 -0
- package/dist/utils/flow-api-discovery.d.ts +151 -0
- package/dist/utils/flow-api-discovery.d.ts.map +1 -0
- package/dist/utils/flow-api-discovery.js +440 -0
- package/dist/utils/flow-api-discovery.js.map +1 -0
- package/dist/utils/flow-xml-generator.d.ts +41 -0
- package/dist/utils/flow-xml-generator.d.ts.map +1 -0
- package/dist/utils/flow-xml-generator.js +258 -0
- package/dist/utils/flow-xml-generator.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +51 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/mcp-auth-middleware.d.ts +58 -0
- package/dist/utils/mcp-auth-middleware.d.ts.map +1 -0
- package/dist/utils/mcp-auth-middleware.js +227 -0
- package/dist/utils/mcp-auth-middleware.js.map +1 -0
- package/dist/utils/mcp-config-manager.d.ts +126 -0
- package/dist/utils/mcp-config-manager.d.ts.map +1 -0
- package/dist/utils/mcp-config-manager.js +209 -0
- package/dist/utils/mcp-config-manager.js.map +1 -0
- package/dist/utils/mcp-server-manager.d.ts +91 -0
- package/dist/utils/mcp-server-manager.d.ts.map +1 -0
- package/dist/utils/mcp-server-manager.js +338 -0
- package/dist/utils/mcp-server-manager.js.map +1 -0
- package/dist/utils/scope-utils.d.ts +72 -0
- package/dist/utils/scope-utils.d.ts.map +1 -0
- package/dist/utils/scope-utils.js +386 -0
- package/dist/utils/scope-utils.js.map +1 -0
- package/dist/utils/servicenow-client.d.ts +233 -0
- package/dist/utils/servicenow-client.d.ts.map +1 -0
- package/dist/utils/servicenow-client.js +1465 -0
- package/dist/utils/servicenow-client.js.map +1 -0
- package/dist/utils/snow-oauth-old.d.ts +65 -0
- package/dist/utils/snow-oauth-old.d.ts.map +1 -0
- package/dist/utils/snow-oauth-old.js +345 -0
- package/dist/utils/snow-oauth-old.js.map +1 -0
- package/dist/utils/snow-oauth.d.ts +85 -0
- package/dist/utils/snow-oauth.d.ts.map +1 -0
- package/dist/utils/snow-oauth.js +512 -0
- package/dist/utils/snow-oauth.js.map +1 -0
- package/dist/utils/template-engine.d.ts +76 -0
- package/dist/utils/template-engine.d.ts.map +1 -0
- package/dist/utils/template-engine.js +391 -0
- package/dist/utils/template-engine.js.map +1 -0
- package/dist/version.d.ts +35 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +72 -0
- package/dist/version.js.map +1 -0
- package/mcp-wrapper.sh +12 -0
- package/package.json +77 -0
- package/reports/swarm-auto-centralized-1752649029776.json +13 -0
- package/scripts/postinstall.js +30 -0
- package/scripts/setup-mcp.js +89 -0
|
@@ -0,0 +1,1287 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* ServiceNow Operations MCP Server
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
17
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
18
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
19
|
+
const servicenow_client_js_1 = require("../utils/servicenow-client.js");
|
|
20
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
21
|
+
// Operational table mappings for ServiceNow
|
|
22
|
+
const operationalTableMapping = {
|
|
23
|
+
// ITIL Core Processes
|
|
24
|
+
incident: 'incident',
|
|
25
|
+
request: 'sc_request',
|
|
26
|
+
request_item: 'sc_req_item',
|
|
27
|
+
problem: 'problem',
|
|
28
|
+
change_request: 'change_request',
|
|
29
|
+
// Task Management
|
|
30
|
+
task: 'task',
|
|
31
|
+
incident_task: 'incident_task',
|
|
32
|
+
problem_task: 'problem_task',
|
|
33
|
+
change_task: 'change_task',
|
|
34
|
+
approval: 'sysapproval_approver',
|
|
35
|
+
// User & Group Management
|
|
36
|
+
user: 'sys_user',
|
|
37
|
+
user_group: 'sys_user_group',
|
|
38
|
+
user_role: 'sys_user_has_role',
|
|
39
|
+
// CMDB (Configuration Management Database)
|
|
40
|
+
configuration_item: 'cmdb_ci',
|
|
41
|
+
server: 'cmdb_ci_server',
|
|
42
|
+
application: 'cmdb_ci_application',
|
|
43
|
+
database: 'cmdb_ci_database',
|
|
44
|
+
network_device: 'cmdb_ci_network_device',
|
|
45
|
+
service: 'cmdb_ci_service',
|
|
46
|
+
// Logging & Audit
|
|
47
|
+
system_log: 'syslog',
|
|
48
|
+
audit_log: 'sys_audit',
|
|
49
|
+
email: 'sys_email',
|
|
50
|
+
attachment: 'sys_attachment',
|
|
51
|
+
// Knowledge Management
|
|
52
|
+
knowledge_base: 'kb_knowledge_base',
|
|
53
|
+
knowledge: 'kb_knowledge',
|
|
54
|
+
// Service Catalog
|
|
55
|
+
catalog: 'sc_catalog',
|
|
56
|
+
catalog_item: 'sc_cat_item',
|
|
57
|
+
// Metrics & Analytics
|
|
58
|
+
metric: 'sys_metric',
|
|
59
|
+
metric_instance: 'sys_metric_instance',
|
|
60
|
+
// Notifications
|
|
61
|
+
notification: 'sysevent_email_action',
|
|
62
|
+
email_log: 'sys_email'
|
|
63
|
+
};
|
|
64
|
+
// Common operational queries for intelligent analysis
|
|
65
|
+
const commonPatterns = {
|
|
66
|
+
// Network connectivity issues
|
|
67
|
+
network_issues: {
|
|
68
|
+
keywords: ['network', 'connectivity', 'ping', 'dns', 'timeout', 'unreachable'],
|
|
69
|
+
common_solutions: [
|
|
70
|
+
'Check network connectivity',
|
|
71
|
+
'Verify DNS resolution',
|
|
72
|
+
'Test ping to server',
|
|
73
|
+
'Review firewall rules'
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
// Database connectivity
|
|
77
|
+
database_issues: {
|
|
78
|
+
keywords: ['database', 'connection', 'sql', 'timeout', 'deadlock', 'performance'],
|
|
79
|
+
common_solutions: [
|
|
80
|
+
'Check database connection',
|
|
81
|
+
'Review connection pool settings',
|
|
82
|
+
'Analyze query performance',
|
|
83
|
+
'Check for blocking processes'
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
// Application errors
|
|
87
|
+
application_errors: {
|
|
88
|
+
keywords: ['application', 'error', 'exception', 'crash', 'memory', 'cpu'],
|
|
89
|
+
common_solutions: [
|
|
90
|
+
'Check application logs',
|
|
91
|
+
'Review memory usage',
|
|
92
|
+
'Analyze CPU utilization',
|
|
93
|
+
'Restart application service'
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
// Authentication issues
|
|
97
|
+
auth_issues: {
|
|
98
|
+
keywords: ['authentication', 'login', 'password', 'ldap', 'sso', 'unauthorized'],
|
|
99
|
+
common_solutions: [
|
|
100
|
+
'Reset user password',
|
|
101
|
+
'Check LDAP connectivity',
|
|
102
|
+
'Verify SSO configuration',
|
|
103
|
+
'Review user permissions'
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
class ServiceNowOperationsMCP {
|
|
108
|
+
constructor() {
|
|
109
|
+
this.server = new index_js_1.Server({
|
|
110
|
+
name: 'servicenow-operations-mcp',
|
|
111
|
+
version: '1.0.0',
|
|
112
|
+
}, {
|
|
113
|
+
capabilities: {
|
|
114
|
+
tools: {},
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
this.client = new servicenow_client_js_1.ServiceNowClient();
|
|
118
|
+
this.setupToolHandlers();
|
|
119
|
+
}
|
|
120
|
+
setupToolHandlers() {
|
|
121
|
+
// List available tools
|
|
122
|
+
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
123
|
+
return {
|
|
124
|
+
tools: [
|
|
125
|
+
// Core Operational Queries
|
|
126
|
+
{
|
|
127
|
+
name: 'snow_query_incidents',
|
|
128
|
+
description: 'Advanced incident querying with filters and analysis',
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
query: {
|
|
133
|
+
type: 'string',
|
|
134
|
+
description: 'ServiceNow encoded query or natural language description'
|
|
135
|
+
},
|
|
136
|
+
limit: {
|
|
137
|
+
type: 'number',
|
|
138
|
+
description: 'Maximum number of results (default: 10)',
|
|
139
|
+
default: 10
|
|
140
|
+
},
|
|
141
|
+
include_analysis: {
|
|
142
|
+
type: 'boolean',
|
|
143
|
+
description: 'Include intelligent analysis of incidents',
|
|
144
|
+
default: false
|
|
145
|
+
},
|
|
146
|
+
fields: {
|
|
147
|
+
type: 'array',
|
|
148
|
+
items: { type: 'string' },
|
|
149
|
+
description: 'Specific fields to return'
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
required: ['query']
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'snow_analyze_incident',
|
|
157
|
+
description: 'Intelligent analysis of a specific incident with auto-resolution suggestions',
|
|
158
|
+
inputSchema: {
|
|
159
|
+
type: 'object',
|
|
160
|
+
properties: {
|
|
161
|
+
incident_id: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
description: 'Incident number or sys_id'
|
|
164
|
+
},
|
|
165
|
+
include_similar: {
|
|
166
|
+
type: 'boolean',
|
|
167
|
+
description: 'Include similar incidents in analysis',
|
|
168
|
+
default: true
|
|
169
|
+
},
|
|
170
|
+
suggest_resolution: {
|
|
171
|
+
type: 'boolean',
|
|
172
|
+
description: 'Generate automated resolution suggestions',
|
|
173
|
+
default: true
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
required: ['incident_id']
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'snow_auto_resolve_incident',
|
|
181
|
+
description: 'Attempt automated resolution of technical incidents',
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: 'object',
|
|
184
|
+
properties: {
|
|
185
|
+
incident_id: {
|
|
186
|
+
type: 'string',
|
|
187
|
+
description: 'Incident number or sys_id'
|
|
188
|
+
},
|
|
189
|
+
dry_run: {
|
|
190
|
+
type: 'boolean',
|
|
191
|
+
description: 'Preview actions without executing',
|
|
192
|
+
default: true
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
required: ['incident_id']
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'snow_query_requests',
|
|
200
|
+
description: 'Query and analyze service requests',
|
|
201
|
+
inputSchema: {
|
|
202
|
+
type: 'object',
|
|
203
|
+
properties: {
|
|
204
|
+
query: {
|
|
205
|
+
type: 'string',
|
|
206
|
+
description: 'ServiceNow encoded query or natural language'
|
|
207
|
+
},
|
|
208
|
+
limit: {
|
|
209
|
+
type: 'number',
|
|
210
|
+
description: 'Maximum number of results',
|
|
211
|
+
default: 10
|
|
212
|
+
},
|
|
213
|
+
include_items: {
|
|
214
|
+
type: 'boolean',
|
|
215
|
+
description: 'Include request items',
|
|
216
|
+
default: false
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
required: ['query']
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: 'snow_query_problems',
|
|
224
|
+
description: 'Query and analyze problems with root cause analysis',
|
|
225
|
+
inputSchema: {
|
|
226
|
+
type: 'object',
|
|
227
|
+
properties: {
|
|
228
|
+
query: {
|
|
229
|
+
type: 'string',
|
|
230
|
+
description: 'ServiceNow encoded query or natural language'
|
|
231
|
+
},
|
|
232
|
+
limit: {
|
|
233
|
+
type: 'number',
|
|
234
|
+
description: 'Maximum number of results',
|
|
235
|
+
default: 10
|
|
236
|
+
},
|
|
237
|
+
include_incidents: {
|
|
238
|
+
type: 'boolean',
|
|
239
|
+
description: 'Include related incidents',
|
|
240
|
+
default: false
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
required: ['query']
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'snow_cmdb_search',
|
|
248
|
+
description: 'Search and analyze Configuration Items (CMDB)',
|
|
249
|
+
inputSchema: {
|
|
250
|
+
type: 'object',
|
|
251
|
+
properties: {
|
|
252
|
+
query: {
|
|
253
|
+
type: 'string',
|
|
254
|
+
description: 'Search query for configuration items'
|
|
255
|
+
},
|
|
256
|
+
ci_type: {
|
|
257
|
+
type: 'string',
|
|
258
|
+
description: 'Type of CI (server, application, service, etc.)',
|
|
259
|
+
enum: ['server', 'application', 'database', 'network_device', 'service', 'any']
|
|
260
|
+
},
|
|
261
|
+
limit: {
|
|
262
|
+
type: 'number',
|
|
263
|
+
description: 'Maximum number of results',
|
|
264
|
+
default: 10
|
|
265
|
+
},
|
|
266
|
+
include_relationships: {
|
|
267
|
+
type: 'boolean',
|
|
268
|
+
description: 'Include CI relationships',
|
|
269
|
+
default: false
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
required: ['query']
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: 'snow_user_lookup',
|
|
277
|
+
description: 'Lookup and analyze user information',
|
|
278
|
+
inputSchema: {
|
|
279
|
+
type: 'object',
|
|
280
|
+
properties: {
|
|
281
|
+
identifier: {
|
|
282
|
+
type: 'string',
|
|
283
|
+
description: 'User ID, email, or name'
|
|
284
|
+
},
|
|
285
|
+
include_roles: {
|
|
286
|
+
type: 'boolean',
|
|
287
|
+
description: 'Include user roles',
|
|
288
|
+
default: true
|
|
289
|
+
},
|
|
290
|
+
include_groups: {
|
|
291
|
+
type: 'boolean',
|
|
292
|
+
description: 'Include user groups',
|
|
293
|
+
default: true
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
required: ['identifier']
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'snow_operational_metrics',
|
|
301
|
+
description: 'Get operational metrics and analytics',
|
|
302
|
+
inputSchema: {
|
|
303
|
+
type: 'object',
|
|
304
|
+
properties: {
|
|
305
|
+
timeframe: {
|
|
306
|
+
type: 'string',
|
|
307
|
+
description: 'Time period for metrics',
|
|
308
|
+
enum: ['today', 'week', 'month', 'quarter'],
|
|
309
|
+
default: 'week'
|
|
310
|
+
},
|
|
311
|
+
metric_types: {
|
|
312
|
+
type: 'array',
|
|
313
|
+
items: { type: 'string' },
|
|
314
|
+
description: 'Types of metrics to include'
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: 'snow_pattern_analysis',
|
|
321
|
+
description: 'Analyze patterns in incidents, requests, and problems',
|
|
322
|
+
inputSchema: {
|
|
323
|
+
type: 'object',
|
|
324
|
+
properties: {
|
|
325
|
+
analysis_type: {
|
|
326
|
+
type: 'string',
|
|
327
|
+
description: 'Type of pattern analysis',
|
|
328
|
+
enum: ['incident_patterns', 'request_trends', 'problem_root_causes', 'user_behavior']
|
|
329
|
+
},
|
|
330
|
+
timeframe: {
|
|
331
|
+
type: 'string',
|
|
332
|
+
description: 'Time period for analysis',
|
|
333
|
+
enum: ['day', 'week', 'month', 'quarter'],
|
|
334
|
+
default: 'week'
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
required: ['analysis_type']
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
name: 'snow_knowledge_search',
|
|
342
|
+
description: 'Search knowledge base articles with intelligent matching',
|
|
343
|
+
inputSchema: {
|
|
344
|
+
type: 'object',
|
|
345
|
+
properties: {
|
|
346
|
+
query: {
|
|
347
|
+
type: 'string',
|
|
348
|
+
description: 'Search query or incident description'
|
|
349
|
+
},
|
|
350
|
+
match_incident: {
|
|
351
|
+
type: 'string',
|
|
352
|
+
description: 'Match knowledge to specific incident'
|
|
353
|
+
},
|
|
354
|
+
limit: {
|
|
355
|
+
type: 'number',
|
|
356
|
+
description: 'Maximum number of results',
|
|
357
|
+
default: 5
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
required: ['query']
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
name: 'snow_predictive_analysis',
|
|
365
|
+
description: 'Predictive analysis for potential issues and trends',
|
|
366
|
+
inputSchema: {
|
|
367
|
+
type: 'object',
|
|
368
|
+
properties: {
|
|
369
|
+
prediction_type: {
|
|
370
|
+
type: 'string',
|
|
371
|
+
description: 'Type of prediction',
|
|
372
|
+
enum: ['incident_volume', 'system_failure', 'resource_exhaustion', 'user_impact']
|
|
373
|
+
},
|
|
374
|
+
timeframe: {
|
|
375
|
+
type: 'string',
|
|
376
|
+
description: 'Prediction timeframe',
|
|
377
|
+
enum: ['day', 'week', 'month'],
|
|
378
|
+
default: 'week'
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
required: ['prediction_type']
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
],
|
|
385
|
+
};
|
|
386
|
+
});
|
|
387
|
+
// Handle tool calls
|
|
388
|
+
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
389
|
+
const { name, arguments: args } = request.params;
|
|
390
|
+
try {
|
|
391
|
+
switch (name) {
|
|
392
|
+
case 'snow_query_incidents':
|
|
393
|
+
return await this.handleQueryIncidents(args);
|
|
394
|
+
case 'snow_analyze_incident':
|
|
395
|
+
return await this.handleAnalyzeIncident(args);
|
|
396
|
+
case 'snow_auto_resolve_incident':
|
|
397
|
+
return await this.handleAutoResolveIncident(args);
|
|
398
|
+
case 'snow_query_requests':
|
|
399
|
+
return await this.handleQueryRequests(args);
|
|
400
|
+
case 'snow_query_problems':
|
|
401
|
+
return await this.handleQueryProblems(args);
|
|
402
|
+
case 'snow_cmdb_search':
|
|
403
|
+
return await this.handleCMDBSearch(args);
|
|
404
|
+
case 'snow_user_lookup':
|
|
405
|
+
return await this.handleUserLookup(args);
|
|
406
|
+
case 'snow_operational_metrics':
|
|
407
|
+
return await this.handleOperationalMetrics(args);
|
|
408
|
+
case 'snow_pattern_analysis':
|
|
409
|
+
return await this.handlePatternAnalysis(args);
|
|
410
|
+
case 'snow_knowledge_search':
|
|
411
|
+
return await this.handleKnowledgeSearch(args);
|
|
412
|
+
case 'snow_predictive_analysis':
|
|
413
|
+
return await this.handlePredictiveAnalysis(args);
|
|
414
|
+
default:
|
|
415
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Tool ${name} not found`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
logger_js_1.logger.error(`Error executing tool ${name}:`, error);
|
|
420
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to execute ${name}: ${error}`);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
async handleQueryIncidents(args) {
|
|
425
|
+
const { query, limit = 10, include_analysis = false, fields } = args;
|
|
426
|
+
logger_js_1.logger.info(`Querying incidents with: ${query}`);
|
|
427
|
+
try {
|
|
428
|
+
// Convert natural language to ServiceNow query if needed
|
|
429
|
+
const processedQuery = this.processNaturalLanguageQuery(query, 'incident');
|
|
430
|
+
// Query incidents
|
|
431
|
+
const incidents = await this.client.searchRecords('incident', processedQuery, limit);
|
|
432
|
+
let result = {
|
|
433
|
+
total_results: incidents.success ? incidents.data.result.length : 0,
|
|
434
|
+
incidents: incidents.success ? incidents.data.result : []
|
|
435
|
+
};
|
|
436
|
+
// Add intelligent analysis if requested
|
|
437
|
+
if (include_analysis && incidents.success && incidents.data.result.length > 0) {
|
|
438
|
+
const analysis = await this.analyzeIncidents(incidents.data.result);
|
|
439
|
+
result = { ...result, ...analysis };
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
content: [
|
|
443
|
+
{
|
|
444
|
+
type: 'text',
|
|
445
|
+
text: `Found ${incidents.success ? incidents.data.result.length : 0} incidents matching query: "${query}"\n\n${JSON.stringify(result, null, 2)}`
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
logger_js_1.logger.error('Error querying incidents:', error);
|
|
452
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to query incidents: ${error}`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
async handleAnalyzeIncident(args) {
|
|
456
|
+
const { incident_id, include_similar = true, suggest_resolution = true } = args;
|
|
457
|
+
logger_js_1.logger.info(`Analyzing incident: ${incident_id}`);
|
|
458
|
+
try {
|
|
459
|
+
// Get incident details
|
|
460
|
+
const incident = await this.getIncidentDetails(incident_id);
|
|
461
|
+
if (!incident) {
|
|
462
|
+
throw new Error(`Incident ${incident_id} not found`);
|
|
463
|
+
}
|
|
464
|
+
// Perform intelligent analysis
|
|
465
|
+
const analysis = await this.performIncidentAnalysis(incident, include_similar, suggest_resolution);
|
|
466
|
+
return {
|
|
467
|
+
content: [
|
|
468
|
+
{
|
|
469
|
+
type: 'text',
|
|
470
|
+
text: `Incident Analysis for ${incident_id}:\n\n${JSON.stringify(analysis, null, 2)}`
|
|
471
|
+
}
|
|
472
|
+
]
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
logger_js_1.logger.error('Error analyzing incident:', error);
|
|
477
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to analyze incident: ${error}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
async handleAutoResolveIncident(args) {
|
|
481
|
+
const { incident_id, dry_run = true } = args;
|
|
482
|
+
logger_js_1.logger.info(`Auto-resolving incident: ${incident_id} (dry_run: ${dry_run})`);
|
|
483
|
+
try {
|
|
484
|
+
// Get incident details
|
|
485
|
+
const incident = await this.getIncidentDetails(incident_id);
|
|
486
|
+
if (!incident) {
|
|
487
|
+
throw new Error(`Incident ${incident_id} not found`);
|
|
488
|
+
}
|
|
489
|
+
// Analyze incident for auto-resolution potential
|
|
490
|
+
const analysis = await this.performIncidentAnalysis(incident, true, true);
|
|
491
|
+
// Generate automated resolution actions
|
|
492
|
+
const resolutionActions = await this.generateResolutionActions(incident, analysis);
|
|
493
|
+
let result = {
|
|
494
|
+
incident_id,
|
|
495
|
+
analysis,
|
|
496
|
+
resolution_actions: resolutionActions,
|
|
497
|
+
dry_run,
|
|
498
|
+
actions_executed: []
|
|
499
|
+
};
|
|
500
|
+
// Execute actions if not dry run
|
|
501
|
+
if (!dry_run && resolutionActions.length > 0) {
|
|
502
|
+
result.actions_executed = await this.executeResolutionActions(incident_id, resolutionActions);
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
content: [
|
|
506
|
+
{
|
|
507
|
+
type: 'text',
|
|
508
|
+
text: `Auto-Resolution Analysis for ${incident_id}:\n\n${JSON.stringify(result, null, 2)}`
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
catch (error) {
|
|
514
|
+
logger_js_1.logger.error('Error auto-resolving incident:', error);
|
|
515
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to auto-resolve incident: ${error}`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async handleQueryRequests(args) {
|
|
519
|
+
const { query, limit = 10, include_items = false } = args;
|
|
520
|
+
logger_js_1.logger.info(`Querying requests with: ${query}`);
|
|
521
|
+
try {
|
|
522
|
+
const processedQuery = this.processNaturalLanguageQuery(query, 'request');
|
|
523
|
+
const requests = await this.client.searchRecords('sc_request', processedQuery, limit);
|
|
524
|
+
let result = {
|
|
525
|
+
total_results: requests.success ? requests.data.result.length : 0,
|
|
526
|
+
requests: requests.success ? requests.data.result : []
|
|
527
|
+
};
|
|
528
|
+
// Include request items if requested
|
|
529
|
+
if (include_items && requests.success && requests.data.result.length > 0) {
|
|
530
|
+
const requestItems = await this.getRequestItems(requests.data.result);
|
|
531
|
+
result = { ...result, request_items: requestItems };
|
|
532
|
+
}
|
|
533
|
+
return {
|
|
534
|
+
content: [
|
|
535
|
+
{
|
|
536
|
+
type: 'text',
|
|
537
|
+
text: `Found ${requests.success ? requests.data.result.length : 0} requests matching query: "${query}"\n\n${JSON.stringify(result, null, 2)}`
|
|
538
|
+
}
|
|
539
|
+
]
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
logger_js_1.logger.error('Error querying requests:', error);
|
|
544
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to query requests: ${error}`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
async handleQueryProblems(args) {
|
|
548
|
+
const { query, limit = 10, include_incidents = false } = args;
|
|
549
|
+
logger_js_1.logger.info(`Querying problems with: ${query}`);
|
|
550
|
+
try {
|
|
551
|
+
const processedQuery = this.processNaturalLanguageQuery(query, 'problem');
|
|
552
|
+
const problems = await this.client.searchRecords('problem', processedQuery, limit);
|
|
553
|
+
let result = {
|
|
554
|
+
total_results: problems.success ? problems.data.result.length : 0,
|
|
555
|
+
problems: problems.success ? problems.data.result : []
|
|
556
|
+
};
|
|
557
|
+
// Include related incidents if requested
|
|
558
|
+
if (include_incidents && problems.success && problems.data.result.length > 0) {
|
|
559
|
+
const incidents = await this.getRelatedIncidents(problems.data.result);
|
|
560
|
+
result = { ...result, related_incidents: incidents };
|
|
561
|
+
}
|
|
562
|
+
return {
|
|
563
|
+
content: [
|
|
564
|
+
{
|
|
565
|
+
type: 'text',
|
|
566
|
+
text: `Found ${problems.success ? problems.data.result.length : 0} problems matching query: "${query}"\n\n${JSON.stringify(result, null, 2)}`
|
|
567
|
+
}
|
|
568
|
+
]
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
catch (error) {
|
|
572
|
+
logger_js_1.logger.error('Error querying problems:', error);
|
|
573
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to query problems: ${error}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
async handleCMDBSearch(args) {
|
|
577
|
+
const { query, ci_type = 'any', limit = 10, include_relationships = false } = args;
|
|
578
|
+
logger_js_1.logger.info(`Searching CMDB with: ${query}, type: ${ci_type}`);
|
|
579
|
+
try {
|
|
580
|
+
const ciTable = ci_type === 'any' ? 'cmdb_ci' : operationalTableMapping[ci_type] || 'cmdb_ci';
|
|
581
|
+
const processedQuery = this.processNaturalLanguageQuery(query, 'cmdb');
|
|
582
|
+
const configItems = await this.client.searchRecords(ciTable, processedQuery, limit);
|
|
583
|
+
let result = {
|
|
584
|
+
total_results: configItems.success ? configItems.data.result.length : 0,
|
|
585
|
+
configuration_items: configItems.success ? configItems.data.result : [],
|
|
586
|
+
ci_type: ci_type
|
|
587
|
+
};
|
|
588
|
+
// Include relationships if requested
|
|
589
|
+
if (include_relationships && configItems.success && configItems.data.result.length > 0) {
|
|
590
|
+
const relationships = await this.getCIRelationships(configItems.data.result);
|
|
591
|
+
result = { ...result, relationships };
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
content: [
|
|
595
|
+
{
|
|
596
|
+
type: 'text',
|
|
597
|
+
text: `Found ${configItems.success ? configItems.data.result.length : 0} configuration items matching query: "${query}"\n\n${JSON.stringify(result, null, 2)}`
|
|
598
|
+
}
|
|
599
|
+
]
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
catch (error) {
|
|
603
|
+
logger_js_1.logger.error('Error searching CMDB:', error);
|
|
604
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to search CMDB: ${error}`);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
async handleUserLookup(args) {
|
|
608
|
+
const { identifier, include_roles = true, include_groups = true } = args;
|
|
609
|
+
logger_js_1.logger.info(`Looking up user: ${identifier}`);
|
|
610
|
+
try {
|
|
611
|
+
// Try different user lookup strategies
|
|
612
|
+
let userQuery = '';
|
|
613
|
+
if (identifier.includes('@')) {
|
|
614
|
+
userQuery = `email=${identifier}`;
|
|
615
|
+
}
|
|
616
|
+
else if (identifier.includes('.')) {
|
|
617
|
+
userQuery = `user_name=${identifier}`;
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
userQuery = `nameLIKE${identifier}^ORuser_nameLIKE${identifier}^ORemailLIKE${identifier}`;
|
|
621
|
+
}
|
|
622
|
+
const users = await this.client.searchRecords('sys_user', userQuery, 5);
|
|
623
|
+
if (!users.success || users.data.result.length === 0) {
|
|
624
|
+
return {
|
|
625
|
+
content: [
|
|
626
|
+
{
|
|
627
|
+
type: 'text',
|
|
628
|
+
text: `No users found matching identifier: "${identifier}"`
|
|
629
|
+
}
|
|
630
|
+
]
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
let result = {
|
|
634
|
+
total_results: users.data.result.length,
|
|
635
|
+
users: users.data.result
|
|
636
|
+
};
|
|
637
|
+
// Include roles and groups if requested
|
|
638
|
+
if (include_roles || include_groups) {
|
|
639
|
+
const userDetails = await this.getUserDetails(users.data.result[0].sys_id, include_roles, include_groups);
|
|
640
|
+
result = { ...result, user_details: userDetails };
|
|
641
|
+
}
|
|
642
|
+
return {
|
|
643
|
+
content: [
|
|
644
|
+
{
|
|
645
|
+
type: 'text',
|
|
646
|
+
text: `Found ${users.success ? users.data.result.length : 0} users matching identifier: "${identifier}"\n\n${JSON.stringify(result, null, 2)}`
|
|
647
|
+
}
|
|
648
|
+
]
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
logger_js_1.logger.error('Error looking up user:', error);
|
|
653
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to lookup user: ${error}`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
async handleOperationalMetrics(args) {
|
|
657
|
+
const { timeframe = 'week', metric_types = [] } = args;
|
|
658
|
+
logger_js_1.logger.info(`Getting operational metrics for timeframe: ${timeframe}`);
|
|
659
|
+
try {
|
|
660
|
+
const metrics = await this.calculateOperationalMetrics(timeframe, metric_types);
|
|
661
|
+
return {
|
|
662
|
+
content: [
|
|
663
|
+
{
|
|
664
|
+
type: 'text',
|
|
665
|
+
text: `Operational Metrics (${timeframe}):\n\n${JSON.stringify(metrics, null, 2)}`
|
|
666
|
+
}
|
|
667
|
+
]
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
catch (error) {
|
|
671
|
+
logger_js_1.logger.error('Error getting operational metrics:', error);
|
|
672
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to get operational metrics: ${error}`);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
async handlePatternAnalysis(args) {
|
|
676
|
+
const { analysis_type, timeframe = 'week' } = args;
|
|
677
|
+
logger_js_1.logger.info(`Performing pattern analysis: ${analysis_type} for ${timeframe}`);
|
|
678
|
+
try {
|
|
679
|
+
const patterns = await this.analyzePatterns(analysis_type, timeframe);
|
|
680
|
+
return {
|
|
681
|
+
content: [
|
|
682
|
+
{
|
|
683
|
+
type: 'text',
|
|
684
|
+
text: `Pattern Analysis (${analysis_type} - ${timeframe}):\n\n${JSON.stringify(patterns, null, 2)}`
|
|
685
|
+
}
|
|
686
|
+
]
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
catch (error) {
|
|
690
|
+
logger_js_1.logger.error('Error analyzing patterns:', error);
|
|
691
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to analyze patterns: ${error}`);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
async handleKnowledgeSearch(args) {
|
|
695
|
+
const { query, match_incident, limit = 5 } = args;
|
|
696
|
+
logger_js_1.logger.info(`Searching knowledge base with: ${query}`);
|
|
697
|
+
try {
|
|
698
|
+
const processedQuery = this.processNaturalLanguageQuery(query, 'knowledge');
|
|
699
|
+
const articles = await this.client.searchRecords('kb_knowledge', processedQuery, limit);
|
|
700
|
+
let result = {
|
|
701
|
+
total_results: articles.success ? articles.data.result.length : 0,
|
|
702
|
+
knowledge_articles: articles.success ? articles.data.result : []
|
|
703
|
+
};
|
|
704
|
+
// If matching to incident, provide relevance scoring
|
|
705
|
+
if (match_incident) {
|
|
706
|
+
const incident = await this.getIncidentDetails(match_incident);
|
|
707
|
+
if (incident) {
|
|
708
|
+
const relevanceScores = await this.calculateKnowledgeRelevance(articles.success ? articles.data.result : [], incident);
|
|
709
|
+
result = { ...result, relevance_scores: relevanceScores };
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return {
|
|
713
|
+
content: [
|
|
714
|
+
{
|
|
715
|
+
type: 'text',
|
|
716
|
+
text: `Found ${articles.success ? articles.data.result.length : 0} knowledge articles matching query: "${query}"\n\n${JSON.stringify(result, null, 2)}`
|
|
717
|
+
}
|
|
718
|
+
]
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
catch (error) {
|
|
722
|
+
logger_js_1.logger.error('Error searching knowledge base:', error);
|
|
723
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to search knowledge base: ${error}`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
async handlePredictiveAnalysis(args) {
|
|
727
|
+
const { prediction_type, timeframe = 'week' } = args;
|
|
728
|
+
logger_js_1.logger.info(`Performing predictive analysis: ${prediction_type} for ${timeframe}`);
|
|
729
|
+
try {
|
|
730
|
+
const predictions = await this.performPredictiveAnalysis(prediction_type, timeframe);
|
|
731
|
+
return {
|
|
732
|
+
content: [
|
|
733
|
+
{
|
|
734
|
+
type: 'text',
|
|
735
|
+
text: `Predictive Analysis (${prediction_type} - ${timeframe}):\n\n${JSON.stringify(predictions, null, 2)}`
|
|
736
|
+
}
|
|
737
|
+
]
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
catch (error) {
|
|
741
|
+
logger_js_1.logger.error('Error performing predictive analysis:', error);
|
|
742
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to perform predictive analysis: ${error}`);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
// Helper methods for intelligent analysis
|
|
746
|
+
processNaturalLanguageQuery(query, context) {
|
|
747
|
+
// Convert natural language to ServiceNow encoded query
|
|
748
|
+
const lowerQuery = query.toLowerCase();
|
|
749
|
+
// Common ServiceNow query patterns
|
|
750
|
+
if (lowerQuery.includes('high priority')) {
|
|
751
|
+
return 'priority=1';
|
|
752
|
+
}
|
|
753
|
+
if (lowerQuery.includes('critical')) {
|
|
754
|
+
return 'priority=1^ORseverity=1';
|
|
755
|
+
}
|
|
756
|
+
if (lowerQuery.includes('open') || lowerQuery.includes('active')) {
|
|
757
|
+
return 'active=true^state!=6^state!=7';
|
|
758
|
+
}
|
|
759
|
+
if (lowerQuery.includes('closed') || lowerQuery.includes('resolved')) {
|
|
760
|
+
return 'state=6^ORstate=7';
|
|
761
|
+
}
|
|
762
|
+
if (lowerQuery.includes('today')) {
|
|
763
|
+
return 'sys_created_onONToday@javascript:gs.daysAgoStart(0)@javascript:gs.daysAgoEnd(0)';
|
|
764
|
+
}
|
|
765
|
+
if (lowerQuery.includes('last week')) {
|
|
766
|
+
return 'sys_created_onONLast week@javascript:gs.daysAgoStart(7)@javascript:gs.daysAgoEnd(1)';
|
|
767
|
+
}
|
|
768
|
+
// Context-specific processing
|
|
769
|
+
if (context === 'incident') {
|
|
770
|
+
if (lowerQuery.includes('network')) {
|
|
771
|
+
return 'categoryLIKEnetwork^ORshort_descriptionLIKEnetwork';
|
|
772
|
+
}
|
|
773
|
+
if (lowerQuery.includes('database')) {
|
|
774
|
+
return 'categoryLIKEdatabase^ORshort_descriptionLIKEdatabase';
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
// Default: treat as general search
|
|
778
|
+
return `short_descriptionLIKE${query}^ORdescriptionLIKE${query}`;
|
|
779
|
+
}
|
|
780
|
+
async analyzeIncidents(incidents) {
|
|
781
|
+
const patterns = [];
|
|
782
|
+
const categories = new Map();
|
|
783
|
+
for (const incident of incidents) {
|
|
784
|
+
// Count categories
|
|
785
|
+
const category = incident.category || 'uncategorized';
|
|
786
|
+
categories.set(category, (categories.get(category) || 0) + 1);
|
|
787
|
+
// Detect patterns
|
|
788
|
+
const description = (incident.short_description || '').toLowerCase();
|
|
789
|
+
for (const [patternName, pattern] of Object.entries(commonPatterns)) {
|
|
790
|
+
if (pattern.keywords.some(keyword => description.includes(keyword))) {
|
|
791
|
+
patterns.push({
|
|
792
|
+
incident_number: incident.number,
|
|
793
|
+
pattern: patternName,
|
|
794
|
+
confidence: 0.8
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return {
|
|
800
|
+
patterns_detected: patterns,
|
|
801
|
+
category_distribution: Object.fromEntries(categories),
|
|
802
|
+
total_analyzed: incidents.length
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
async getIncidentDetails(incident_id) {
|
|
806
|
+
// Try to get incident by number first, then by sys_id
|
|
807
|
+
let query = `number=${incident_id}`;
|
|
808
|
+
let incidents = await this.client.searchRecords('incident', query, 1);
|
|
809
|
+
if (!incidents.success || incidents.data.result.length === 0) {
|
|
810
|
+
// Try by sys_id
|
|
811
|
+
query = `sys_id=${incident_id}`;
|
|
812
|
+
incidents = await this.client.searchRecords('incident', query, 1);
|
|
813
|
+
}
|
|
814
|
+
return (incidents.success && incidents.data.result.length > 0) ? incidents.data.result[0] : null;
|
|
815
|
+
}
|
|
816
|
+
async performIncidentAnalysis(incident, include_similar, suggest_resolution) {
|
|
817
|
+
const analysis = {
|
|
818
|
+
incident_id: incident.number,
|
|
819
|
+
patterns_found: [],
|
|
820
|
+
root_cause_analysis: '',
|
|
821
|
+
suggested_resolution: [],
|
|
822
|
+
confidence_score: 0,
|
|
823
|
+
similar_incidents: [],
|
|
824
|
+
knowledge_articles: [],
|
|
825
|
+
automated_actions: []
|
|
826
|
+
};
|
|
827
|
+
// Pattern detection
|
|
828
|
+
const description = (incident.short_description || '').toLowerCase();
|
|
829
|
+
for (const [patternName, pattern] of Object.entries(commonPatterns)) {
|
|
830
|
+
if (pattern.keywords.some(keyword => description.includes(keyword))) {
|
|
831
|
+
analysis.patterns_found.push(patternName);
|
|
832
|
+
analysis.suggested_resolution.push(...pattern.common_solutions);
|
|
833
|
+
analysis.confidence_score += 0.2;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
// Find similar incidents
|
|
837
|
+
if (include_similar) {
|
|
838
|
+
const similarQuery = `short_descriptionLIKE${incident.short_description}^sys_id!=${incident.sys_id}^state=6`;
|
|
839
|
+
const similarIncidents = await this.client.searchRecords('incident', similarQuery, 5);
|
|
840
|
+
analysis.similar_incidents = similarIncidents.success ? similarIncidents.data.result : [];
|
|
841
|
+
}
|
|
842
|
+
// Root cause analysis
|
|
843
|
+
analysis.root_cause_analysis = this.generateRootCauseAnalysis(incident, analysis.patterns_found);
|
|
844
|
+
// Search knowledge base
|
|
845
|
+
const kbQuery = `textLIKE${incident.short_description}^workflow_state=published`;
|
|
846
|
+
const kbArticles = await this.client.searchRecords('kb_knowledge', kbQuery, 3);
|
|
847
|
+
analysis.knowledge_articles = kbArticles.success ? kbArticles.data.result : [];
|
|
848
|
+
// Automated actions
|
|
849
|
+
analysis.automated_actions = this.generateAutomatedActions(incident, analysis.patterns_found);
|
|
850
|
+
return analysis;
|
|
851
|
+
}
|
|
852
|
+
generateRootCauseAnalysis(incident, patterns) {
|
|
853
|
+
if (patterns.length === 0) {
|
|
854
|
+
return 'No specific patterns detected. Manual investigation required.';
|
|
855
|
+
}
|
|
856
|
+
const analysis = [];
|
|
857
|
+
if (patterns.includes('network_issues')) {
|
|
858
|
+
analysis.push('Network connectivity issue detected. Check network infrastructure, DNS, and firewall rules.');
|
|
859
|
+
}
|
|
860
|
+
if (patterns.includes('database_issues')) {
|
|
861
|
+
analysis.push('Database connectivity or performance issue detected. Check database server, connection pools, and query performance.');
|
|
862
|
+
}
|
|
863
|
+
if (patterns.includes('application_errors')) {
|
|
864
|
+
analysis.push('Application error detected. Check application logs, resource utilization, and service status.');
|
|
865
|
+
}
|
|
866
|
+
if (patterns.includes('auth_issues')) {
|
|
867
|
+
analysis.push('Authentication issue detected. Check user credentials, LDAP/SSO configuration, and permissions.');
|
|
868
|
+
}
|
|
869
|
+
return analysis.join(' ');
|
|
870
|
+
}
|
|
871
|
+
generateAutomatedActions(incident, patterns) {
|
|
872
|
+
const actions = [];
|
|
873
|
+
if (patterns.includes('network_issues')) {
|
|
874
|
+
actions.push('Execute network connectivity test');
|
|
875
|
+
actions.push('Check DNS resolution');
|
|
876
|
+
actions.push('Verify firewall rules');
|
|
877
|
+
}
|
|
878
|
+
if (patterns.includes('database_issues')) {
|
|
879
|
+
actions.push('Test database connectivity');
|
|
880
|
+
actions.push('Check database performance metrics');
|
|
881
|
+
actions.push('Review connection pool status');
|
|
882
|
+
}
|
|
883
|
+
if (patterns.includes('application_errors')) {
|
|
884
|
+
actions.push('Restart application service');
|
|
885
|
+
actions.push('Check application logs');
|
|
886
|
+
actions.push('Monitor resource utilization');
|
|
887
|
+
}
|
|
888
|
+
if (patterns.includes('auth_issues')) {
|
|
889
|
+
actions.push('Reset user session');
|
|
890
|
+
actions.push('Verify user permissions');
|
|
891
|
+
actions.push('Check authentication service status');
|
|
892
|
+
}
|
|
893
|
+
return actions;
|
|
894
|
+
}
|
|
895
|
+
async generateResolutionActions(incident, analysis) {
|
|
896
|
+
const actions = [];
|
|
897
|
+
// Add high-confidence automated actions
|
|
898
|
+
if (analysis.confidence_score > 0.6) {
|
|
899
|
+
actions.push(...analysis.automated_actions);
|
|
900
|
+
}
|
|
901
|
+
// Add knowledge-based actions
|
|
902
|
+
if (analysis.knowledge_articles.length > 0) {
|
|
903
|
+
actions.push('Apply resolution from knowledge article');
|
|
904
|
+
}
|
|
905
|
+
// Add pattern-based actions
|
|
906
|
+
if (analysis.similar_incidents.length > 0) {
|
|
907
|
+
actions.push('Apply resolution from similar incident');
|
|
908
|
+
}
|
|
909
|
+
return actions;
|
|
910
|
+
}
|
|
911
|
+
async executeResolutionActions(incident_id, actions) {
|
|
912
|
+
const executed = [];
|
|
913
|
+
for (const action of actions) {
|
|
914
|
+
try {
|
|
915
|
+
// This would integrate with actual automation systems
|
|
916
|
+
logger_js_1.logger.info(`Executing action: ${action} for incident ${incident_id}`);
|
|
917
|
+
executed.push(`✅ ${action}`);
|
|
918
|
+
}
|
|
919
|
+
catch (error) {
|
|
920
|
+
executed.push(`❌ ${action}: ${error}`);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
return executed;
|
|
924
|
+
}
|
|
925
|
+
async getRequestItems(requests) {
|
|
926
|
+
const items = [];
|
|
927
|
+
for (const request of requests) {
|
|
928
|
+
const requestItems = await this.client.searchRecords('sc_req_item', `request=${request.sys_id}`, 10);
|
|
929
|
+
if (requestItems.success) {
|
|
930
|
+
items.push(...requestItems.data.result);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
return items;
|
|
934
|
+
}
|
|
935
|
+
async getRelatedIncidents(problems) {
|
|
936
|
+
const incidents = [];
|
|
937
|
+
for (const problem of problems) {
|
|
938
|
+
const relatedIncidents = await this.client.searchRecords('incident', `problem_id=${problem.sys_id}`, 10);
|
|
939
|
+
if (relatedIncidents.success) {
|
|
940
|
+
incidents.push(...relatedIncidents.data.result);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return incidents;
|
|
944
|
+
}
|
|
945
|
+
async getCIRelationships(configItems) {
|
|
946
|
+
const relationships = [];
|
|
947
|
+
for (const ci of configItems) {
|
|
948
|
+
try {
|
|
949
|
+
const ciRelationships = await this.client.searchRecords('cmdb_rel_ci', `parent=${ci.sys_id}^ORchild=${ci.sys_id}`, 10);
|
|
950
|
+
relationships.push({
|
|
951
|
+
ci_id: ci.sys_id,
|
|
952
|
+
ci_name: ci.name,
|
|
953
|
+
relationships: ciRelationships
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
catch (error) {
|
|
957
|
+
logger_js_1.logger.error(`Error getting relationships for CI ${ci.sys_id}:`, error);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
return relationships;
|
|
961
|
+
}
|
|
962
|
+
async getUserDetails(userId, include_roles, include_groups) {
|
|
963
|
+
const details = {};
|
|
964
|
+
if (include_roles) {
|
|
965
|
+
details.roles = await this.client.searchRecords('sys_user_has_role', `user=${userId}`, 20);
|
|
966
|
+
}
|
|
967
|
+
if (include_groups) {
|
|
968
|
+
details.groups = await this.client.searchRecords('sys_user_grmember', `user=${userId}`, 20);
|
|
969
|
+
}
|
|
970
|
+
return details;
|
|
971
|
+
}
|
|
972
|
+
async calculateOperationalMetrics(timeframe, metricTypes) {
|
|
973
|
+
const dateFilter = this.getDateFilter(timeframe);
|
|
974
|
+
const metrics = {
|
|
975
|
+
total_incidents: 0,
|
|
976
|
+
open_incidents: 0,
|
|
977
|
+
high_priority_incidents: 0,
|
|
978
|
+
avg_resolution_time: 0,
|
|
979
|
+
common_categories: [],
|
|
980
|
+
trending_issues: []
|
|
981
|
+
};
|
|
982
|
+
try {
|
|
983
|
+
// Get total incidents
|
|
984
|
+
const totalIncidents = await this.client.searchRecords('incident', `sys_created_on${dateFilter}`, 1000);
|
|
985
|
+
metrics.total_incidents = totalIncidents.success ? totalIncidents.data.result.length : 0;
|
|
986
|
+
// Get open incidents
|
|
987
|
+
const openIncidents = await this.client.searchRecords('incident', `active=true^sys_created_on${dateFilter}`, 1000);
|
|
988
|
+
metrics.open_incidents = openIncidents.success ? openIncidents.data.result.length : 0;
|
|
989
|
+
// Get high priority incidents
|
|
990
|
+
const highPriorityIncidents = await this.client.searchRecords('incident', `priority=1^sys_created_on${dateFilter}`, 1000);
|
|
991
|
+
metrics.high_priority_incidents = highPriorityIncidents.success ? highPriorityIncidents.data.result.length : 0;
|
|
992
|
+
// Calculate common categories
|
|
993
|
+
const categories = new Map();
|
|
994
|
+
if (totalIncidents.success) {
|
|
995
|
+
totalIncidents.data.result.forEach((incident) => {
|
|
996
|
+
const category = incident.category || 'uncategorized';
|
|
997
|
+
categories.set(category, (categories.get(category) || 0) + 1);
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
metrics.common_categories = Array.from(categories.entries())
|
|
1001
|
+
.sort((a, b) => b[1] - a[1])
|
|
1002
|
+
.slice(0, 5)
|
|
1003
|
+
.map(([category, count]) => `${category}: ${count}`);
|
|
1004
|
+
}
|
|
1005
|
+
catch (error) {
|
|
1006
|
+
logger_js_1.logger.error('Error calculating operational metrics:', error);
|
|
1007
|
+
}
|
|
1008
|
+
return metrics;
|
|
1009
|
+
}
|
|
1010
|
+
getDateFilter(timeframe) {
|
|
1011
|
+
switch (timeframe) {
|
|
1012
|
+
case 'today':
|
|
1013
|
+
return 'ONToday@javascript:gs.daysAgoStart(0)@javascript:gs.daysAgoEnd(0)';
|
|
1014
|
+
case 'week':
|
|
1015
|
+
return 'ONLast 7 days@javascript:gs.daysAgoStart(7)@javascript:gs.daysAgoEnd(0)';
|
|
1016
|
+
case 'month':
|
|
1017
|
+
return 'ONLast 30 days@javascript:gs.daysAgoStart(30)@javascript:gs.daysAgoEnd(0)';
|
|
1018
|
+
case 'quarter':
|
|
1019
|
+
return 'ONLast 90 days@javascript:gs.daysAgoStart(90)@javascript:gs.daysAgoEnd(0)';
|
|
1020
|
+
default:
|
|
1021
|
+
return 'ONLast 7 days@javascript:gs.daysAgoStart(7)@javascript:gs.daysAgoEnd(0)';
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
async analyzePatterns(analysisType, timeframe) {
|
|
1025
|
+
const dateFilter = this.getDateFilter(timeframe);
|
|
1026
|
+
switch (analysisType) {
|
|
1027
|
+
case 'incident_patterns':
|
|
1028
|
+
return await this.analyzeIncidentPatterns(dateFilter);
|
|
1029
|
+
case 'request_trends':
|
|
1030
|
+
return await this.analyzeRequestTrends(dateFilter);
|
|
1031
|
+
case 'problem_root_causes':
|
|
1032
|
+
return await this.analyzeProblemRootCauses(dateFilter);
|
|
1033
|
+
case 'user_behavior':
|
|
1034
|
+
return await this.analyzeUserBehavior(dateFilter);
|
|
1035
|
+
default:
|
|
1036
|
+
return { error: 'Unknown analysis type' };
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
async analyzeIncidentPatterns(dateFilter) {
|
|
1040
|
+
const incidents = await this.client.searchRecords('incident', `sys_created_on${dateFilter}`, 1000);
|
|
1041
|
+
const patterns = {
|
|
1042
|
+
by_category: new Map(),
|
|
1043
|
+
by_priority: new Map(),
|
|
1044
|
+
by_state: new Map(),
|
|
1045
|
+
by_hour: new Map(),
|
|
1046
|
+
common_keywords: new Map()
|
|
1047
|
+
};
|
|
1048
|
+
if (incidents.success) {
|
|
1049
|
+
incidents.data.result.forEach((incident) => {
|
|
1050
|
+
// Category patterns
|
|
1051
|
+
const category = incident.category || 'uncategorized';
|
|
1052
|
+
patterns.by_category.set(category, (patterns.by_category.get(category) || 0) + 1);
|
|
1053
|
+
// Priority patterns
|
|
1054
|
+
const priority = incident.priority || 'unknown';
|
|
1055
|
+
patterns.by_priority.set(priority, (patterns.by_priority.get(priority) || 0) + 1);
|
|
1056
|
+
// State patterns
|
|
1057
|
+
const state = incident.state || 'unknown';
|
|
1058
|
+
patterns.by_state.set(state, (patterns.by_state.get(state) || 0) + 1);
|
|
1059
|
+
// Time patterns
|
|
1060
|
+
if (incident.sys_created_on) {
|
|
1061
|
+
const hour = new Date(incident.sys_created_on).getHours();
|
|
1062
|
+
patterns.by_hour.set(hour, (patterns.by_hour.get(hour) || 0) + 1);
|
|
1063
|
+
}
|
|
1064
|
+
// Keyword patterns
|
|
1065
|
+
const description = (incident.short_description || '').toLowerCase();
|
|
1066
|
+
const keywords = description.split(/\s+/).filter((word) => word.length > 3);
|
|
1067
|
+
keywords.forEach((keyword) => {
|
|
1068
|
+
patterns.common_keywords.set(keyword, (patterns.common_keywords.get(keyword) || 0) + 1);
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
return {
|
|
1073
|
+
total_incidents: incidents.success ? incidents.data.result.length : 0,
|
|
1074
|
+
patterns: {
|
|
1075
|
+
by_category: Object.fromEntries(patterns.by_category),
|
|
1076
|
+
by_priority: Object.fromEntries(patterns.by_priority),
|
|
1077
|
+
by_state: Object.fromEntries(patterns.by_state),
|
|
1078
|
+
by_hour: Object.fromEntries(patterns.by_hour),
|
|
1079
|
+
top_keywords: Array.from(patterns.common_keywords.entries())
|
|
1080
|
+
.sort((a, b) => b[1] - a[1])
|
|
1081
|
+
.slice(0, 10)
|
|
1082
|
+
.map(([keyword, count]) => ({ keyword, count }))
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
async analyzeRequestTrends(dateFilter) {
|
|
1087
|
+
const requests = await this.client.searchRecords('sc_request', `sys_created_on${dateFilter}`, 1000);
|
|
1088
|
+
const trends = {
|
|
1089
|
+
by_state: new Map(),
|
|
1090
|
+
by_requested_for: new Map(),
|
|
1091
|
+
by_approval_status: new Map()
|
|
1092
|
+
};
|
|
1093
|
+
if (requests.success) {
|
|
1094
|
+
requests.data.result.forEach((request) => {
|
|
1095
|
+
const state = request.state || 'unknown';
|
|
1096
|
+
trends.by_state.set(state, (trends.by_state.get(state) || 0) + 1);
|
|
1097
|
+
const requestedFor = request.requested_for || 'unknown';
|
|
1098
|
+
trends.by_requested_for.set(requestedFor, (trends.by_requested_for.get(requestedFor) || 0) + 1);
|
|
1099
|
+
const approvalStatus = request.approval || 'unknown';
|
|
1100
|
+
trends.by_approval_status.set(approvalStatus, (trends.by_approval_status.get(approvalStatus) || 0) + 1);
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
return {
|
|
1104
|
+
total_requests: requests.success ? requests.data.result.length : 0,
|
|
1105
|
+
trends: {
|
|
1106
|
+
by_state: Object.fromEntries(trends.by_state),
|
|
1107
|
+
top_requesters: Array.from(trends.by_requested_for.entries())
|
|
1108
|
+
.sort((a, b) => b[1] - a[1])
|
|
1109
|
+
.slice(0, 10),
|
|
1110
|
+
by_approval_status: Object.fromEntries(trends.by_approval_status)
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
async analyzeProblemRootCauses(dateFilter) {
|
|
1115
|
+
const problems = await this.client.searchRecords('problem', `sys_created_on${dateFilter}`, 1000);
|
|
1116
|
+
const rootCauses = {
|
|
1117
|
+
by_category: new Map(),
|
|
1118
|
+
by_state: new Map(),
|
|
1119
|
+
resolution_patterns: new Map()
|
|
1120
|
+
};
|
|
1121
|
+
if (problems.success) {
|
|
1122
|
+
problems.data.result.forEach((problem) => {
|
|
1123
|
+
const category = problem.category || 'uncategorized';
|
|
1124
|
+
rootCauses.by_category.set(category, (rootCauses.by_category.get(category) || 0) + 1);
|
|
1125
|
+
const state = problem.state || 'unknown';
|
|
1126
|
+
rootCauses.by_state.set(state, (rootCauses.by_state.get(state) || 0) + 1);
|
|
1127
|
+
if (problem.resolution_notes) {
|
|
1128
|
+
const resolution = problem.resolution_notes.toLowerCase();
|
|
1129
|
+
// Simple pattern matching for resolution types
|
|
1130
|
+
if (resolution.includes('restart')) {
|
|
1131
|
+
rootCauses.resolution_patterns.set('restart', (rootCauses.resolution_patterns.get('restart') || 0) + 1);
|
|
1132
|
+
}
|
|
1133
|
+
if (resolution.includes('configuration')) {
|
|
1134
|
+
rootCauses.resolution_patterns.set('configuration', (rootCauses.resolution_patterns.get('configuration') || 0) + 1);
|
|
1135
|
+
}
|
|
1136
|
+
if (resolution.includes('patch') || resolution.includes('update')) {
|
|
1137
|
+
rootCauses.resolution_patterns.set('patch/update', (rootCauses.resolution_patterns.get('patch/update') || 0) + 1);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
return {
|
|
1143
|
+
total_problems: problems.success ? problems.data.result.length : 0,
|
|
1144
|
+
root_causes: {
|
|
1145
|
+
by_category: Object.fromEntries(rootCauses.by_category),
|
|
1146
|
+
by_state: Object.fromEntries(rootCauses.by_state),
|
|
1147
|
+
resolution_patterns: Object.fromEntries(rootCauses.resolution_patterns)
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
async analyzeUserBehavior(dateFilter) {
|
|
1152
|
+
// This would require analyzing user activity across multiple tables
|
|
1153
|
+
// For now, return a basic analysis
|
|
1154
|
+
return {
|
|
1155
|
+
message: 'User behavior analysis requires additional data collection and processing',
|
|
1156
|
+
available_metrics: ['login_patterns', 'request_frequency', 'incident_reporting']
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
async calculateKnowledgeRelevance(articles, incident) {
|
|
1160
|
+
const relevanceScores = [];
|
|
1161
|
+
const incidentDescription = (incident.short_description || '').toLowerCase();
|
|
1162
|
+
const incidentKeywords = incidentDescription.split(/\s+/).filter((word) => word.length > 3);
|
|
1163
|
+
articles.forEach(article => {
|
|
1164
|
+
const articleText = (article.text || '').toLowerCase();
|
|
1165
|
+
const articleKeywords = articleText.split(/\s+/).filter((word) => word.length > 3);
|
|
1166
|
+
// Simple relevance scoring based on keyword overlap
|
|
1167
|
+
const commonKeywords = incidentKeywords.filter((keyword) => articleKeywords.includes(keyword));
|
|
1168
|
+
const relevanceScore = commonKeywords.length / Math.max(incidentKeywords.length, 1);
|
|
1169
|
+
relevanceScores.push({
|
|
1170
|
+
article_id: article.sys_id,
|
|
1171
|
+
article_title: article.title,
|
|
1172
|
+
relevance_score: relevanceScore,
|
|
1173
|
+
common_keywords: commonKeywords
|
|
1174
|
+
});
|
|
1175
|
+
});
|
|
1176
|
+
return relevanceScores.sort((a, b) => b.relevance_score - a.relevance_score);
|
|
1177
|
+
}
|
|
1178
|
+
async performPredictiveAnalysis(predictionType, timeframe) {
|
|
1179
|
+
// This would require machine learning models and historical data analysis
|
|
1180
|
+
// For now, return basic predictions based on current trends
|
|
1181
|
+
const currentDate = new Date();
|
|
1182
|
+
const predictions = {
|
|
1183
|
+
prediction_type: predictionType,
|
|
1184
|
+
timeframe: timeframe,
|
|
1185
|
+
generated_at: currentDate.toISOString(),
|
|
1186
|
+
confidence: 0.7,
|
|
1187
|
+
predictions: []
|
|
1188
|
+
};
|
|
1189
|
+
switch (predictionType) {
|
|
1190
|
+
case 'incident_volume':
|
|
1191
|
+
predictions.predictions = await this.predictIncidentVolume(timeframe);
|
|
1192
|
+
break;
|
|
1193
|
+
case 'system_failure':
|
|
1194
|
+
predictions.predictions = await this.predictSystemFailure(timeframe);
|
|
1195
|
+
break;
|
|
1196
|
+
case 'resource_exhaustion':
|
|
1197
|
+
predictions.predictions = await this.predictResourceExhaustion(timeframe);
|
|
1198
|
+
break;
|
|
1199
|
+
case 'user_impact':
|
|
1200
|
+
predictions.predictions = await this.predictUserImpact(timeframe);
|
|
1201
|
+
break;
|
|
1202
|
+
default:
|
|
1203
|
+
predictions.predictions = [{ error: 'Unknown prediction type' }];
|
|
1204
|
+
}
|
|
1205
|
+
return predictions;
|
|
1206
|
+
}
|
|
1207
|
+
async predictIncidentVolume(timeframe) {
|
|
1208
|
+
// Get historical incident data
|
|
1209
|
+
const historicalData = await this.client.searchRecords('incident', 'sys_created_onONLast 30 days@javascript:gs.daysAgoStart(30)@javascript:gs.daysAgoEnd(0)', 1000);
|
|
1210
|
+
const dailyVolume = new Map();
|
|
1211
|
+
if (historicalData.success) {
|
|
1212
|
+
historicalData.data.result.forEach((incident) => {
|
|
1213
|
+
const date = new Date(incident.sys_created_on).toDateString();
|
|
1214
|
+
dailyVolume.set(date, (dailyVolume.get(date) || 0) + 1);
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
const avgDailyVolume = Array.from(dailyVolume.values()).reduce((a, b) => a + b, 0) / dailyVolume.size;
|
|
1218
|
+
return [
|
|
1219
|
+
{
|
|
1220
|
+
metric: 'daily_incident_volume',
|
|
1221
|
+
predicted_value: Math.round(avgDailyVolume * 1.1), // Simple trend prediction
|
|
1222
|
+
current_average: Math.round(avgDailyVolume),
|
|
1223
|
+
trend: 'increasing',
|
|
1224
|
+
confidence: 0.6
|
|
1225
|
+
}
|
|
1226
|
+
];
|
|
1227
|
+
}
|
|
1228
|
+
async predictSystemFailure(timeframe) {
|
|
1229
|
+
// Analyze problem records and incident patterns
|
|
1230
|
+
const problems = await this.client.searchRecords('problem', 'sys_created_onONLast 30 days@javascript:gs.daysAgoStart(30)@javascript:gs.daysAgoEnd(0)', 100);
|
|
1231
|
+
const systemFailures = problems.success ? problems.data.result.filter((problem) => (problem.short_description || '').toLowerCase().includes('system') ||
|
|
1232
|
+
(problem.short_description || '').toLowerCase().includes('failure') ||
|
|
1233
|
+
(problem.short_description || '').toLowerCase().includes('outage')) : [];
|
|
1234
|
+
return [
|
|
1235
|
+
{
|
|
1236
|
+
metric: 'system_failure_risk',
|
|
1237
|
+
predicted_value: systemFailures.length > 5 ? 'high' : 'medium',
|
|
1238
|
+
current_problems: systemFailures.length,
|
|
1239
|
+
risk_factors: ['Historical system problems', 'Incident patterns'],
|
|
1240
|
+
confidence: 0.5
|
|
1241
|
+
}
|
|
1242
|
+
];
|
|
1243
|
+
}
|
|
1244
|
+
async predictResourceExhaustion(timeframe) {
|
|
1245
|
+
// This would require integration with monitoring systems
|
|
1246
|
+
return [
|
|
1247
|
+
{
|
|
1248
|
+
metric: 'resource_exhaustion_risk',
|
|
1249
|
+
predicted_value: 'low',
|
|
1250
|
+
message: 'Resource exhaustion prediction requires monitoring system integration',
|
|
1251
|
+
confidence: 0.3
|
|
1252
|
+
}
|
|
1253
|
+
];
|
|
1254
|
+
}
|
|
1255
|
+
async predictUserImpact(timeframe) {
|
|
1256
|
+
// Analyze user-reported incidents
|
|
1257
|
+
const userIncidents = await this.client.searchRecords('incident', 'sys_created_onONLast 7 days@javascript:gs.daysAgoStart(7)@javascript:gs.daysAgoEnd(0)^priority=1', 100);
|
|
1258
|
+
const impactLevels = new Map();
|
|
1259
|
+
if (userIncidents.success) {
|
|
1260
|
+
userIncidents.data.result.forEach((incident) => {
|
|
1261
|
+
const impact = incident.impact || 'unknown';
|
|
1262
|
+
impactLevels.set(impact, (impactLevels.get(impact) || 0) + 1);
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
return [
|
|
1266
|
+
{
|
|
1267
|
+
metric: 'user_impact_prediction',
|
|
1268
|
+
predicted_value: impactLevels.get('1') > 5 ? 'high' : 'medium',
|
|
1269
|
+
current_high_impact: impactLevels.get('1') || 0,
|
|
1270
|
+
trend_factors: ['High priority incidents', 'User complaints'],
|
|
1271
|
+
confidence: 0.6
|
|
1272
|
+
}
|
|
1273
|
+
];
|
|
1274
|
+
}
|
|
1275
|
+
async run() {
|
|
1276
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
1277
|
+
await this.server.connect(transport);
|
|
1278
|
+
logger_js_1.logger.info('ServiceNow Operations MCP Server started');
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
// Start the server
|
|
1282
|
+
const server = new ServiceNowOperationsMCP();
|
|
1283
|
+
server.run().catch((error) => {
|
|
1284
|
+
logger_js_1.logger.error('Failed to start ServiceNow Operations MCP server:', error);
|
|
1285
|
+
process.exit(1);
|
|
1286
|
+
});
|
|
1287
|
+
//# sourceMappingURL=servicenow-operations-mcp.js.map
|