snow-flow 10.0.196 → 10.0.198
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/package.json +2 -1
- package/src/cli/cmd/tui/component/dialog-auth.tsx +18 -14
- package/src/servicenow/servicenow-mcp-unified/tools/automation/snow_execute_script.ts +67 -35
- package/src/servicenow/servicenow-mcp-unified/tools/index.ts +0 -18
- package/src/servicenow/servicenow-mcp-unified/tools/platform/snow_create_ui_policy.ts +25 -4
- package/src/servicenow/servicenow-mcp-unified/tools/security/snow_analyze_threat_intelligence.ts +2 -4
- package/src/servicenow/servicenow-mcp-unified/tools/security/snow_audit_trail_analysis.ts +1 -3
- package/src/servicenow/servicenow-mcp-unified/tools/security/snow_automate_threat_response.ts +2 -4
- package/src/servicenow/servicenow-mcp-unified/tools/security/snow_create_access_control.ts +2 -4
- package/src/servicenow/servicenow-mcp-unified/tools/security/snow_create_audit_rule.ts +1 -3
- package/src/servicenow/servicenow-mcp-unified/tools/ui-policies/link-ui-policy.ts +84 -0
- package/src/servicenow/servicenow-mcp-unified/tools/ui-policies/snow_create_ui_policy_action.ts +68 -31
- package/src/servicenow/shared/mcp-prompt-manager.ts +7 -7
- package/tsconfig.servicenow.json +20 -0
- package/src/servicenow/base-mcp-server.ts +0 -732
- package/src/servicenow/cli/auth.ts +0 -669
- package/src/servicenow/cli/deploy-artifact.ts +0 -304
- package/src/servicenow/cli/enterprise-refresh.ts +0 -93
- package/src/servicenow/cli/enterprise.ts +0 -446
- package/src/servicenow/cli/session.ts +0 -45
- package/src/servicenow/config/snow-code-config.ts +0 -154
- package/src/servicenow/index.ts +0 -126
- package/src/servicenow/mcp-config.ts +0 -157
- package/src/servicenow/servicenow-automation-mcp.ts +0 -2895
- package/src/servicenow/servicenow-change-virtualagent-pa-mcp-enhanced.ts +0 -974
- package/src/servicenow/servicenow-change-virtualagent-pa-mcp.ts +0 -1466
- package/src/servicenow/servicenow-cmdb-event-hr-csm-devops-mcp-enhanced.ts +0 -1311
- package/src/servicenow/servicenow-cmdb-event-hr-csm-devops-mcp.ts +0 -1616
- package/src/servicenow/servicenow-deployment-mcp.ts +0 -10306
- package/src/servicenow/servicenow-development-assistant-mcp.ts +0 -4925
- package/src/servicenow/servicenow-flow-workspace-mobile-mcp-enhanced.ts +0 -1038
- package/src/servicenow/servicenow-flow-workspace-mobile-mcp.ts +0 -4311
- package/src/servicenow/servicenow-integration-mcp.ts +0 -906
- package/src/servicenow/servicenow-itam-mcp.ts +0 -673
- package/src/servicenow/servicenow-knowledge-catalog-mcp-enhanced.ts +0 -836
- package/src/servicenow/servicenow-knowledge-catalog-mcp.ts +0 -1898
- package/src/servicenow/servicenow-local-development-mcp.ts +0 -629
- package/src/servicenow/servicenow-machine-learning-mcp.ts +0 -4095
- package/src/servicenow/servicenow-mcp-server.ts +0 -736
- package/src/servicenow/servicenow-mcp-unified/tools/ai-ml-MIGRATED/index.ts +0 -5
- package/src/servicenow/servicenow-mcp-unified/tools/ai-ml-MIGRATED/snow_predict.ts +0 -44
- package/src/servicenow/servicenow-mcp-unified/tools/ai-ml-MIGRATED/snow_train_classifier.ts +0 -46
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/README.md +0 -149
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/index.ts +0 -48
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_classify_incident.ts +0 -197
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_detect_anomalies.ts +0 -191
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_forecast_incidents.ts +0 -273
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_hybrid_recommendation.ts +0 -346
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_performance_analytics.ts +0 -232
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_predict_change_risk.ts +0 -186
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_train_anomaly_detector.ts +0 -298
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_train_change_risk.ts +0 -267
- package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_train_incident_classifier.ts +0 -386
- package/src/servicenow/servicenow-mcp-unified/tools/script-includes/index.ts +0 -4
- package/src/servicenow/servicenow-mcp-unified/tools/ui-actions/index.ts +0 -4
- package/src/servicenow/servicenow-notifications-mcp.ts +0 -413
- package/src/servicenow/servicenow-operations-mcp.ts +0 -4041
- package/src/servicenow/servicenow-platform-development-mcp.ts +0 -1081
- package/src/servicenow/servicenow-progressive-indexer.ts +0 -366
- package/src/servicenow/servicenow-reporting-analytics-mcp.ts +0 -1485
- package/src/servicenow/servicenow-secops-mcp.ts +0 -690
- package/src/servicenow/servicenow-security-compliance-mcp.ts +0 -1267
- package/src/servicenow/servicenow-system-properties-mcp.ts +0 -1339
- package/src/servicenow/servicenow-update-set-mcp.ts +0 -964
- package/src/servicenow/shared/MCP-PROMPTS.md +0 -226
- package/src/servicenow/shared/agent-context-provider.ts +0 -354
- package/src/servicenow/shared/base-mcp-server.ts +0 -2570
- package/src/servicenow/shared/enhanced-base-mcp-server.ts +0 -387
- package/src/servicenow/shared/mcp-logger.ts +0 -269
- package/src/servicenow/shared/mcp-memory-manager.ts +0 -567
- package/src/servicenow/shared/mcp-resource-manager.ts +0 -367
- package/src/servicenow/shared/mcp-types.ts +0 -58
- package/src/servicenow/shared/reliable-memory-manager.ts +0 -315
- package/src/servicenow/shared/response-limiter.ts +0 -129
- package/src/servicenow/utils/dynamic-models.ts +0 -101
- package/src/servicenow/utils/logger.ts +0 -99
- package/src/servicenow/utils/memory-safe-collections.ts +0 -235
- package/src/servicenow/utils/servicenow-client.ts +0 -3530
- package/src/servicenow/utils/snow-oauth.ts +0 -1164
- package/src/servicenow/utils/sync-mcp-configs.ts +0 -114
- package/src/servicenow/utils/timer-registry.ts +0 -346
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.198",
|
|
4
4
|
"name": "snow-flow",
|
|
5
5
|
"description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
|
|
6
6
|
"license": "Elastic-2.0",
|
|
7
7
|
"private": false,
|
|
8
8
|
"scripts": {
|
|
9
9
|
"typecheck": "tsgo --noEmit",
|
|
10
|
+
"typecheck:servicenow": "tsgo --project tsconfig.servicenow.json --noEmit",
|
|
10
11
|
"test": "bun test",
|
|
11
12
|
"build": "bun run script/build.ts",
|
|
12
13
|
"dev": "bun run --conditions=browser ./src/index.ts",
|
|
@@ -1105,31 +1105,35 @@ function DialogAuthEnterprise() {
|
|
|
1105
1105
|
}),
|
|
1106
1106
|
})
|
|
1107
1107
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1108
|
+
const responseData = await response.json().catch(() => ({}))
|
|
1109
|
+
|
|
1110
|
+
// 202 = pending approval, or explicit pending status
|
|
1111
|
+
const isPending = response.status === 202 || responseData.status === "pending" || responseData.error === "pending"
|
|
1112
|
+
if (isPending && attempt < maxAttempts) {
|
|
1113
|
+
toast.show({ variant: "info", message: `Waiting for browser approval... (${attempt}/${maxAttempts})`, duration: 2000 })
|
|
1114
|
+
await new Promise(r => setTimeout(r, 2000))
|
|
1115
|
+
continue
|
|
1111
1116
|
}
|
|
1112
1117
|
|
|
1113
|
-
|
|
1118
|
+
if (response.ok && !isPending) {
|
|
1119
|
+
data = responseData
|
|
1120
|
+
break
|
|
1121
|
+
}
|
|
1114
1122
|
|
|
1115
1123
|
// Billing redirect — not retryable
|
|
1116
|
-
if (
|
|
1117
|
-
toast.show({ variant: "error", message:
|
|
1124
|
+
if (responseData.billingUrl) {
|
|
1125
|
+
toast.show({ variant: "error", message: responseData.message || responseData.error || "Subscription required", duration: 8000 })
|
|
1118
1126
|
toast.show({ variant: "info", message: "Opening billing page...", duration: 4000 })
|
|
1119
|
-
tryOpenBrowser(
|
|
1127
|
+
tryOpenBrowser(responseData.billingUrl)
|
|
1120
1128
|
setStep("code")
|
|
1121
1129
|
return
|
|
1122
1130
|
}
|
|
1123
1131
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
if (isPending && attempt < maxAttempts) {
|
|
1127
|
-
toast.show({ variant: "info", message: `Waiting for browser approval... (${attempt}/${maxAttempts})`, duration: 2000 })
|
|
1128
|
-
await new Promise(r => setTimeout(r, 2000))
|
|
1129
|
-
continue
|
|
1132
|
+
if (isPending) {
|
|
1133
|
+
throw new Error("Verification timed out — please approve in your browser and try again")
|
|
1130
1134
|
}
|
|
1131
1135
|
|
|
1132
|
-
throw new Error(
|
|
1136
|
+
throw new Error(responseData.error || "Verification failed")
|
|
1133
1137
|
}
|
|
1134
1138
|
|
|
1135
1139
|
if (!data) {
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
* ES5 only! ServiceNow runs on Rhino engine.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { MCPToolDefinition, ServiceNowContext, ToolResult } from "../../shared/types.js"
|
|
11
|
+
import type { MCPToolDefinition, ServiceNowContext, ToolResult } from "../../shared/types.js"
|
|
12
12
|
import { getAuthenticatedClient } from "../../shared/auth.js"
|
|
13
13
|
import { createSuccessResult, createErrorResult, SnowFlowError, ErrorType } from "../../shared/error-handler.js"
|
|
14
|
-
import
|
|
14
|
+
import { randomBytes } from "crypto"
|
|
15
15
|
|
|
16
16
|
const ENDPOINT_SERVICE_ID = "snow_flow_exec"
|
|
17
17
|
const ENDPOINT_PATH = "/execute"
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const endpointCache = new Map<string, { namespace: string }>()
|
|
20
20
|
|
|
21
21
|
const OPERATION_SCRIPT = `(function process(request, response) {
|
|
22
22
|
var body = request.body.data;
|
|
@@ -213,53 +213,85 @@ export async function execute(args: Record<string, unknown>, context: ServiceNow
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
function getEndpointUrl(context: ServiceNowContext): string {
|
|
217
|
+
const cached = endpointCache.get(context.instanceUrl)
|
|
218
|
+
if (cached) return `/api/${cached.namespace}/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`
|
|
219
|
+
return `/api/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`
|
|
220
|
+
}
|
|
221
|
+
|
|
216
222
|
async function ensureEndpoint(context: ServiceNowContext): Promise<boolean> {
|
|
217
|
-
if (
|
|
223
|
+
if (endpointCache.has(context.instanceUrl)) return true
|
|
218
224
|
|
|
219
225
|
const client = await getAuthenticatedClient(context)
|
|
220
226
|
|
|
221
227
|
const check = await client.get("/api/now/table/sys_ws_definition", {
|
|
222
228
|
params: {
|
|
223
229
|
sysparm_query: `service_id=${ENDPOINT_SERVICE_ID}`,
|
|
224
|
-
sysparm_fields: "sys_id",
|
|
230
|
+
sysparm_fields: "sys_id,namespace,base_uri",
|
|
225
231
|
sysparm_limit: 1,
|
|
226
232
|
},
|
|
227
233
|
})
|
|
228
234
|
|
|
229
235
|
const existing = check.data?.result?.[0]
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
const svcId =
|
|
237
|
+
existing?.sys_id ||
|
|
238
|
+
(await (async () => {
|
|
239
|
+
const svc = await client.post("/api/now/table/sys_ws_definition", {
|
|
240
|
+
name: "Snow-Flow Script Executor",
|
|
241
|
+
service_id: ENDPOINT_SERVICE_ID,
|
|
242
|
+
short_description: "Synchronous script execution endpoint for Snow-Flow",
|
|
243
|
+
active: true,
|
|
244
|
+
})
|
|
237
245
|
|
|
238
|
-
|
|
239
|
-
|
|
246
|
+
const id = svc.data?.result?.sys_id
|
|
247
|
+
if (!id) return null
|
|
240
248
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
await client.post("/api/now/table/sys_ws_operation", {
|
|
250
|
+
name: "Execute Script",
|
|
251
|
+
web_service_definition: id,
|
|
252
|
+
http_method: "POST",
|
|
253
|
+
relative_path: ENDPOINT_PATH,
|
|
254
|
+
operation_script: OPERATION_SCRIPT,
|
|
255
|
+
active: true,
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
return id
|
|
259
|
+
})())
|
|
260
|
+
|
|
261
|
+
if (!svcId) return false
|
|
249
262
|
|
|
250
|
-
|
|
263
|
+
const svcRecord =
|
|
264
|
+
existing ||
|
|
265
|
+
(
|
|
266
|
+
await client
|
|
267
|
+
.get("/api/now/table/sys_ws_definition/" + svcId, {
|
|
268
|
+
params: { sysparm_fields: "namespace,base_uri" },
|
|
269
|
+
})
|
|
270
|
+
.catch(() => null)
|
|
271
|
+
)?.data?.result
|
|
272
|
+
|
|
273
|
+
const ns = svcRecord?.namespace || ""
|
|
274
|
+
|
|
275
|
+
const candidates = ns
|
|
276
|
+
? [`/api/${ns}/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`, `/api/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`]
|
|
277
|
+
: [`/api/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`]
|
|
278
|
+
|
|
279
|
+
for (const url of candidates) {
|
|
280
|
+
const ping = await client.post(url, { script: "'pong'", execution_id: "deploy_verify" }).catch(() => null)
|
|
281
|
+
|
|
282
|
+
if (ping?.data?.result?.success === true) {
|
|
283
|
+
const parts = url.replace(`/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`, "").replace("/api/", "")
|
|
284
|
+
endpointCache.set(context.instanceUrl, { namespace: parts || ENDPOINT_SERVICE_ID })
|
|
285
|
+
return true
|
|
286
|
+
}
|
|
251
287
|
}
|
|
252
288
|
|
|
253
|
-
|
|
254
|
-
.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
})
|
|
258
|
-
.catch(() => null)
|
|
289
|
+
if (ns) {
|
|
290
|
+
endpointCache.set(context.instanceUrl, { namespace: ns })
|
|
291
|
+
return true
|
|
292
|
+
}
|
|
259
293
|
|
|
260
|
-
|
|
261
|
-
if (ok) deployed.set(context.instanceUrl, true)
|
|
262
|
-
return ok
|
|
294
|
+
return false
|
|
263
295
|
}
|
|
264
296
|
|
|
265
297
|
async function executeViaSyncApi(
|
|
@@ -276,7 +308,7 @@ async function executeViaSyncApi(
|
|
|
276
308
|
const client = await getAuthenticatedClient(context)
|
|
277
309
|
|
|
278
310
|
const response = await client
|
|
279
|
-
.post(
|
|
311
|
+
.post(getEndpointUrl(context), {
|
|
280
312
|
script: params.script,
|
|
281
313
|
execution_id: params.executionId,
|
|
282
314
|
})
|
|
@@ -346,7 +378,7 @@ async function executeViaScheduler(
|
|
|
346
378
|
const escape = (str: string) =>
|
|
347
379
|
str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r")
|
|
348
380
|
|
|
349
|
-
const executionId = `exec_${Date.now()}_${
|
|
381
|
+
const executionId = `exec_${Date.now()}_${randomBytes(6).toString("hex")}`
|
|
350
382
|
const marker = `SNOW_FLOW_EXEC_${executionId}`
|
|
351
383
|
|
|
352
384
|
const wrapped = `
|
|
@@ -561,7 +593,7 @@ async function executeScript(
|
|
|
561
593
|
},
|
|
562
594
|
context: ServiceNowContext,
|
|
563
595
|
): Promise<ToolResult> {
|
|
564
|
-
const executionId = `exec_${Date.now()}_${
|
|
596
|
+
const executionId = `exec_${Date.now()}_${randomBytes(6).toString("hex")}`
|
|
565
597
|
|
|
566
598
|
const syncResult = await executeViaSyncApi({ ...params, executionId }, context)
|
|
567
599
|
if (syncResult) return syncResult
|
|
@@ -56,9 +56,6 @@ export * from "./lists/index.js"
|
|
|
56
56
|
// Business Rules (2 tools)
|
|
57
57
|
export * from "./business-rules/index.js"
|
|
58
58
|
|
|
59
|
-
// Script Includes (1 tool)
|
|
60
|
-
export * from "./script-includes/index.js"
|
|
61
|
-
|
|
62
59
|
// REST API tools moved to Integration folder (see snow_rest_message_manage, snow_create_rest_message)
|
|
63
60
|
|
|
64
61
|
// SLA (2 tools)
|
|
@@ -94,9 +91,6 @@ export * from "./journals/index.js"
|
|
|
94
91
|
// Data Policies (2 tools)
|
|
95
92
|
export * from "./data-policies/index.js"
|
|
96
93
|
|
|
97
|
-
// UI Actions (1 tool)
|
|
98
|
-
export * from "./ui-actions/index.js"
|
|
99
|
-
|
|
100
94
|
// Workspace (10 tools)
|
|
101
95
|
export * from "./workspace/index.js"
|
|
102
96
|
|
|
@@ -187,9 +181,6 @@ export * from "./project/index.js"
|
|
|
187
181
|
// Performance Analytics (3 tools)
|
|
188
182
|
export * from "./performance-analytics/index.js"
|
|
189
183
|
|
|
190
|
-
// Predictive Intelligence (5 tools)
|
|
191
|
-
export * from "./predictive-intelligence/index.js"
|
|
192
|
-
|
|
193
184
|
// Service Portal (3 tools)
|
|
194
185
|
export * from "./service-portal/index.js"
|
|
195
186
|
|
|
@@ -217,12 +208,6 @@ export * from "./notifications/index.js"
|
|
|
217
208
|
// Mobile (3 tools)
|
|
218
209
|
export * from "./mobile/index.js"
|
|
219
210
|
|
|
220
|
-
// AI & ML (3 tools)
|
|
221
|
-
export * from "./ai-ml/index.js"
|
|
222
|
-
|
|
223
|
-
// Machine Learning - TensorFlow.js Neural Networks (9 tools)
|
|
224
|
-
export * from "./machine-learning/index.js"
|
|
225
|
-
|
|
226
211
|
// ATF (Automated Test Framework) (6 tools)
|
|
227
212
|
export * from "./atf/index.js"
|
|
228
213
|
|
|
@@ -244,9 +229,6 @@ export * from "./integration/index.js"
|
|
|
244
229
|
// Platform (8 tools)
|
|
245
230
|
export * from "./platform/index.js"
|
|
246
231
|
|
|
247
|
-
// Monitoring (1 tool)
|
|
248
|
-
export * from "./monitoring/index.js"
|
|
249
|
-
|
|
250
232
|
// Blast Radius (5 tools)
|
|
251
233
|
export * from "./blast-radius/index.js"
|
|
252
234
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { MCPToolDefinition, ServiceNowContext, ToolResult } from "../../shared/types.js"
|
|
9
9
|
import { getAuthenticatedClient } from "../../shared/auth.js"
|
|
10
10
|
import { createSuccessResult, createErrorResult } from "../../shared/error-handler.js"
|
|
11
|
+
import { linkUiPolicyReference, verifyUiPolicyLink } from "../ui-policies/link-ui-policy.js"
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Extract sys_id from API response - handles both string and object formats
|
|
@@ -129,6 +130,7 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
129
130
|
|
|
130
131
|
// Create UI Policy Actions
|
|
131
132
|
const createdActions = []
|
|
133
|
+
const unlinkableActions: string[] = []
|
|
132
134
|
for (const action of actions) {
|
|
133
135
|
const actionData: any = {
|
|
134
136
|
ui_policy: policySysId,
|
|
@@ -140,10 +142,20 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
const actionResponse = await client.post("/api/now/table/sys_ui_policy_action", actionData)
|
|
143
|
-
|
|
145
|
+
const actionResult = actionResponse.data.result
|
|
146
|
+
const actionSysId = extractSysId(actionResult.sys_id)
|
|
147
|
+
|
|
148
|
+
// Verify ui_policy link; if POST didn't set it, use fallback chain
|
|
149
|
+
const alreadyLinked = await verifyUiPolicyLink(client, actionSysId, policySysId)
|
|
150
|
+
if (!alreadyLinked) {
|
|
151
|
+
const linked = await linkUiPolicyReference(client, actionSysId, policySysId)
|
|
152
|
+
if (!linked) unlinkableActions.push(action.field_name)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
createdActions.push(actionResult)
|
|
144
156
|
}
|
|
145
157
|
|
|
146
|
-
|
|
158
|
+
const result: Record<string, any> = {
|
|
147
159
|
created: true,
|
|
148
160
|
ui_policy: {
|
|
149
161
|
sys_id: policySysId,
|
|
@@ -161,7 +173,7 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
161
173
|
mandatory: action.mandatory === "true",
|
|
162
174
|
readonly: action.readonly === "true",
|
|
163
175
|
cleared: action.cleared === "true",
|
|
164
|
-
|
|
176
|
+
ui_policy_linked: !unlinkableActions.includes(action.field),
|
|
165
177
|
})),
|
|
166
178
|
total_actions: createdActions.length,
|
|
167
179
|
best_practices: [
|
|
@@ -171,7 +183,16 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
171
183
|
"Order matters when multiple policies affect same field",
|
|
172
184
|
"Test with different user roles and data",
|
|
173
185
|
],
|
|
174
|
-
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (unlinkableActions.length > 0) {
|
|
189
|
+
result.warning =
|
|
190
|
+
"Some actions could not be linked to the UI policy: " +
|
|
191
|
+
unlinkableActions.join(", ") +
|
|
192
|
+
". Link them manually in the ServiceNow UI."
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return createSuccessResult(result)
|
|
175
196
|
} catch (error: any) {
|
|
176
197
|
return createErrorResult(error.message)
|
|
177
198
|
}
|
package/src/servicenow/servicenow-mcp-unified/tools/security/snow_analyze_threat_intelligence.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"
|
|
2
|
-
import type { ServiceNowClient } from "../../../../utils/servicenow-client.js"
|
|
3
|
-
import type { MCPLogger } from "../../../shared/mcp-logger.js"
|
|
4
2
|
import { MCPToolDefinition, ToolResult } from "../../shared/types.js"
|
|
5
3
|
import { ServiceNowContext } from "../../shared/types.js"
|
|
6
4
|
|
|
@@ -66,8 +64,8 @@ export interface AnalyzeThreatIntelligenceArgs {
|
|
|
66
64
|
|
|
67
65
|
export async function analyzeThreatIntelligence(
|
|
68
66
|
args: AnalyzeThreatIntelligenceArgs,
|
|
69
|
-
client:
|
|
70
|
-
logger:
|
|
67
|
+
client: any,
|
|
68
|
+
logger: any,
|
|
71
69
|
) {
|
|
72
70
|
try {
|
|
73
71
|
const { ioc_value, ioc_type, threat_feed_sources = [], correlation_timeframe = "24_hours" } = args
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"
|
|
2
|
-
import type { ServiceNowClient } from "../../../../utils/servicenow-client.js"
|
|
3
|
-
import type { MCPLogger } from "../../../shared/mcp-logger.js"
|
|
4
2
|
import { MCPToolDefinition, ToolResult, ServiceNowContext } from "../../shared/types.js"
|
|
5
3
|
|
|
6
4
|
export const toolDefinition: MCPToolDefinition = {
|
|
@@ -63,7 +61,7 @@ export interface AuditTrailAnalysisArgs {
|
|
|
63
61
|
exportFormat?: "json" | "csv" | "pdf"
|
|
64
62
|
}
|
|
65
63
|
|
|
66
|
-
export async function auditTrailAnalysis(args: AuditTrailAnalysisArgs, client:
|
|
64
|
+
export async function auditTrailAnalysis(args: AuditTrailAnalysisArgs, client: any, logger: any) {
|
|
67
65
|
try {
|
|
68
66
|
const timeframe = args.timeframe || "24h"
|
|
69
67
|
let query = ""
|
package/src/servicenow/servicenow-mcp-unified/tools/security/snow_automate_threat_response.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"
|
|
2
|
-
import type { ServiceNowClient } from "../../../../utils/servicenow-client.js"
|
|
3
|
-
import type { MCPLogger } from "../../../shared/mcp-logger.js"
|
|
4
2
|
import { MCPToolDefinition, ToolResult, ServiceNowContext } from "../../shared/types.js"
|
|
5
3
|
|
|
6
4
|
export const toolDefinition: MCPToolDefinition = {
|
|
@@ -64,8 +62,8 @@ export interface AutomateThreatResponseArgs {
|
|
|
64
62
|
|
|
65
63
|
export async function automateThreatResponse(
|
|
66
64
|
args: AutomateThreatResponseArgs,
|
|
67
|
-
client:
|
|
68
|
-
logger:
|
|
65
|
+
client: any,
|
|
66
|
+
logger: any,
|
|
69
67
|
) {
|
|
70
68
|
try {
|
|
71
69
|
const { threat_id, response_level, automated_actions = false, notification_groups = [] } = args
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"
|
|
2
|
-
import type { ServiceNowClient } from "../../../../utils/servicenow-client.js"
|
|
3
|
-
import type { MCPLogger } from "../../../shared/mcp-logger.js"
|
|
4
2
|
import { MCPToolDefinition, ToolResult, ServiceNowContext } from "../../shared/types.js"
|
|
5
3
|
|
|
6
4
|
export const toolDefinition: MCPToolDefinition = {
|
|
@@ -76,7 +74,7 @@ export interface CreateAccessControlArgs {
|
|
|
76
74
|
active?: boolean
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
export async function createAccessControl(args: CreateAccessControlArgs, client:
|
|
77
|
+
export async function createAccessControl(args: CreateAccessControlArgs, client: any, logger: any) {
|
|
80
78
|
try {
|
|
81
79
|
logger.info("Creating Access Control...")
|
|
82
80
|
|
|
@@ -118,7 +116,7 @@ export async function createAccessControl(args: CreateAccessControlArgs, client:
|
|
|
118
116
|
|
|
119
117
|
async function getTableInfo(
|
|
120
118
|
tableName: string,
|
|
121
|
-
client:
|
|
119
|
+
client: any,
|
|
122
120
|
): Promise<{ name: string; label: string } | null> {
|
|
123
121
|
try {
|
|
124
122
|
const tableResponse = await client.searchRecords("sys_db_object", `name=${tableName}`, 1)
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"
|
|
2
|
-
import type { ServiceNowClient } from "../../../../utils/servicenow-client.js"
|
|
3
|
-
import type { MCPLogger } from "../../../shared/mcp-logger.js"
|
|
4
2
|
import { MCPToolDefinition, ToolResult, ServiceNowContext } from "../../shared/types.js"
|
|
5
3
|
|
|
6
4
|
export const toolDefinition: MCPToolDefinition = {
|
|
@@ -79,7 +77,7 @@ export interface CreateAuditRuleArgs {
|
|
|
79
77
|
active?: boolean
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
export async function createAuditRule(args: CreateAuditRuleArgs, client:
|
|
80
|
+
export async function createAuditRule(args: CreateAuditRuleArgs, client: any, logger: any) {
|
|
83
81
|
try {
|
|
84
82
|
logger.info("Creating Audit Rule...")
|
|
85
83
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper to link a sys_ui_policy_action record to its parent UI policy.
|
|
3
|
+
*
|
|
4
|
+
* ServiceNow's REST Table API POST silently ignores the "ui_policy" reference
|
|
5
|
+
* field on sys_ui_policy_action during creation. This module provides a
|
|
6
|
+
* cascading fallback (PATCH → PUT → GlideRecord) to set the reference after
|
|
7
|
+
* the record has been created.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { AxiosInstance } from "axios"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Verify that the ui_policy reference field is set on a sys_ui_policy_action record.
|
|
14
|
+
*/
|
|
15
|
+
export async function verifyUiPolicyLink(
|
|
16
|
+
client: AxiosInstance,
|
|
17
|
+
actionSysId: string,
|
|
18
|
+
expectedSysId: string,
|
|
19
|
+
): Promise<boolean> {
|
|
20
|
+
try {
|
|
21
|
+
const res = await client.get(
|
|
22
|
+
"/api/now/table/sys_ui_policy_action/" + actionSysId + "?sysparm_fields=ui_policy",
|
|
23
|
+
)
|
|
24
|
+
const ref = res.data.result?.ui_policy
|
|
25
|
+
const val = typeof ref === "object" && ref !== null ? ref.value : ref
|
|
26
|
+
return !!val && val !== "" && val === expectedSysId
|
|
27
|
+
} catch {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Attempt to link a sys_ui_policy_action record to its parent UI policy using
|
|
34
|
+
* a cascading fallback chain:
|
|
35
|
+
* Tier 1 — PATCH (standard Table API update)
|
|
36
|
+
* Tier 2 — PUT (full record update)
|
|
37
|
+
* Tier 3 — GlideRecord via Scripted REST endpoint (last resort)
|
|
38
|
+
*
|
|
39
|
+
* Returns true if the link was successfully set and verified.
|
|
40
|
+
*/
|
|
41
|
+
export async function linkUiPolicyReference(
|
|
42
|
+
client: AxiosInstance,
|
|
43
|
+
actionSysId: string,
|
|
44
|
+
uiPolicySysId: string,
|
|
45
|
+
): Promise<boolean> {
|
|
46
|
+
const url = "/api/now/table/sys_ui_policy_action/" + actionSysId
|
|
47
|
+
const body = { ui_policy: uiPolicySysId }
|
|
48
|
+
|
|
49
|
+
// Tier 1: PATCH
|
|
50
|
+
try {
|
|
51
|
+
await client.patch(url, body)
|
|
52
|
+
if (await verifyUiPolicyLink(client, actionSysId, uiPolicySysId)) return true
|
|
53
|
+
} catch {
|
|
54
|
+
// fall through
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Tier 2: PUT
|
|
58
|
+
try {
|
|
59
|
+
await client.put(url, body)
|
|
60
|
+
if (await verifyUiPolicyLink(client, actionSysId, uiPolicySysId)) return true
|
|
61
|
+
} catch {
|
|
62
|
+
// fall through
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Tier 3: GlideRecord via Scripted REST endpoint
|
|
66
|
+
try {
|
|
67
|
+
const script =
|
|
68
|
+
"var gr = new GlideRecord('sys_ui_policy_action');\n" +
|
|
69
|
+
"gr.get('" + actionSysId + "');\n" +
|
|
70
|
+
"gr.setValue('ui_policy', '" + uiPolicySysId + "');\n" +
|
|
71
|
+
"gr.update();\n" +
|
|
72
|
+
"gs.print(gr.getValue('ui_policy'));"
|
|
73
|
+
|
|
74
|
+
await client.post("/api/snow_flow_exec/execute", {
|
|
75
|
+
script,
|
|
76
|
+
execution_id: "link_ui_policy_" + actionSysId,
|
|
77
|
+
})
|
|
78
|
+
if (await verifyUiPolicyLink(client, actionSysId, uiPolicySysId)) return true
|
|
79
|
+
} catch {
|
|
80
|
+
// all tiers exhausted
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return false
|
|
84
|
+
}
|