snow-flow 10.0.196 → 10.0.197

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/package.json +2 -1
  2. package/src/cli/cmd/tui/component/dialog-auth.tsx +18 -14
  3. package/src/servicenow/servicenow-mcp-unified/tools/automation/snow_execute_script.ts +67 -35
  4. package/src/servicenow/servicenow-mcp-unified/tools/index.ts +0 -18
  5. package/src/servicenow/servicenow-mcp-unified/tools/security/snow_analyze_threat_intelligence.ts +2 -4
  6. package/src/servicenow/servicenow-mcp-unified/tools/security/snow_audit_trail_analysis.ts +1 -3
  7. package/src/servicenow/servicenow-mcp-unified/tools/security/snow_automate_threat_response.ts +2 -4
  8. package/src/servicenow/servicenow-mcp-unified/tools/security/snow_create_access_control.ts +2 -4
  9. package/src/servicenow/servicenow-mcp-unified/tools/security/snow_create_audit_rule.ts +1 -3
  10. package/src/servicenow/servicenow-mcp-unified/tools/ui-policies/snow_create_ui_policy_action.ts +86 -31
  11. package/src/servicenow/shared/mcp-prompt-manager.ts +7 -7
  12. package/tsconfig.servicenow.json +20 -0
  13. package/src/servicenow/base-mcp-server.ts +0 -732
  14. package/src/servicenow/cli/auth.ts +0 -669
  15. package/src/servicenow/cli/deploy-artifact.ts +0 -304
  16. package/src/servicenow/cli/enterprise-refresh.ts +0 -93
  17. package/src/servicenow/cli/enterprise.ts +0 -446
  18. package/src/servicenow/cli/session.ts +0 -45
  19. package/src/servicenow/config/snow-code-config.ts +0 -154
  20. package/src/servicenow/index.ts +0 -126
  21. package/src/servicenow/mcp-config.ts +0 -157
  22. package/src/servicenow/servicenow-automation-mcp.ts +0 -2895
  23. package/src/servicenow/servicenow-change-virtualagent-pa-mcp-enhanced.ts +0 -974
  24. package/src/servicenow/servicenow-change-virtualagent-pa-mcp.ts +0 -1466
  25. package/src/servicenow/servicenow-cmdb-event-hr-csm-devops-mcp-enhanced.ts +0 -1311
  26. package/src/servicenow/servicenow-cmdb-event-hr-csm-devops-mcp.ts +0 -1616
  27. package/src/servicenow/servicenow-deployment-mcp.ts +0 -10306
  28. package/src/servicenow/servicenow-development-assistant-mcp.ts +0 -4925
  29. package/src/servicenow/servicenow-flow-workspace-mobile-mcp-enhanced.ts +0 -1038
  30. package/src/servicenow/servicenow-flow-workspace-mobile-mcp.ts +0 -4311
  31. package/src/servicenow/servicenow-integration-mcp.ts +0 -906
  32. package/src/servicenow/servicenow-itam-mcp.ts +0 -673
  33. package/src/servicenow/servicenow-knowledge-catalog-mcp-enhanced.ts +0 -836
  34. package/src/servicenow/servicenow-knowledge-catalog-mcp.ts +0 -1898
  35. package/src/servicenow/servicenow-local-development-mcp.ts +0 -629
  36. package/src/servicenow/servicenow-machine-learning-mcp.ts +0 -4095
  37. package/src/servicenow/servicenow-mcp-server.ts +0 -736
  38. package/src/servicenow/servicenow-mcp-unified/tools/ai-ml-MIGRATED/index.ts +0 -5
  39. package/src/servicenow/servicenow-mcp-unified/tools/ai-ml-MIGRATED/snow_predict.ts +0 -44
  40. package/src/servicenow/servicenow-mcp-unified/tools/ai-ml-MIGRATED/snow_train_classifier.ts +0 -46
  41. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/README.md +0 -149
  42. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/index.ts +0 -48
  43. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_classify_incident.ts +0 -197
  44. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_detect_anomalies.ts +0 -191
  45. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_forecast_incidents.ts +0 -273
  46. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_hybrid_recommendation.ts +0 -346
  47. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_performance_analytics.ts +0 -232
  48. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_predict_change_risk.ts +0 -186
  49. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_train_anomaly_detector.ts +0 -298
  50. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_train_change_risk.ts +0 -267
  51. package/src/servicenow/servicenow-mcp-unified/tools/machine-learning-MIGRATED/ml_train_incident_classifier.ts +0 -386
  52. package/src/servicenow/servicenow-mcp-unified/tools/script-includes/index.ts +0 -4
  53. package/src/servicenow/servicenow-mcp-unified/tools/ui-actions/index.ts +0 -4
  54. package/src/servicenow/servicenow-notifications-mcp.ts +0 -413
  55. package/src/servicenow/servicenow-operations-mcp.ts +0 -4041
  56. package/src/servicenow/servicenow-platform-development-mcp.ts +0 -1081
  57. package/src/servicenow/servicenow-progressive-indexer.ts +0 -366
  58. package/src/servicenow/servicenow-reporting-analytics-mcp.ts +0 -1485
  59. package/src/servicenow/servicenow-secops-mcp.ts +0 -690
  60. package/src/servicenow/servicenow-security-compliance-mcp.ts +0 -1267
  61. package/src/servicenow/servicenow-system-properties-mcp.ts +0 -1339
  62. package/src/servicenow/servicenow-update-set-mcp.ts +0 -964
  63. package/src/servicenow/shared/MCP-PROMPTS.md +0 -226
  64. package/src/servicenow/shared/agent-context-provider.ts +0 -354
  65. package/src/servicenow/shared/base-mcp-server.ts +0 -2570
  66. package/src/servicenow/shared/enhanced-base-mcp-server.ts +0 -387
  67. package/src/servicenow/shared/mcp-logger.ts +0 -269
  68. package/src/servicenow/shared/mcp-memory-manager.ts +0 -567
  69. package/src/servicenow/shared/mcp-resource-manager.ts +0 -367
  70. package/src/servicenow/shared/mcp-types.ts +0 -58
  71. package/src/servicenow/shared/reliable-memory-manager.ts +0 -315
  72. package/src/servicenow/shared/response-limiter.ts +0 -129
  73. package/src/servicenow/utils/dynamic-models.ts +0 -101
  74. package/src/servicenow/utils/logger.ts +0 -99
  75. package/src/servicenow/utils/memory-safe-collections.ts +0 -235
  76. package/src/servicenow/utils/servicenow-client.ts +0 -3530
  77. package/src/servicenow/utils/snow-oauth.ts +0 -1164
  78. package/src/servicenow/utils/sync-mcp-configs.ts +0 -114
  79. 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.196",
3
+ "version": "10.0.197",
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
- if (response.ok) {
1109
- data = await response.json()
1110
- break
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
- const err = await response.json().catch(() => ({}))
1118
+ if (response.ok && !isPending) {
1119
+ data = responseData
1120
+ break
1121
+ }
1114
1122
 
1115
1123
  // Billing redirect — not retryable
1116
- if (err.billingUrl) {
1117
- toast.show({ variant: "error", message: err.message || err.error || "Subscription required", duration: 8000 })
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(err.billingUrl)
1127
+ tryOpenBrowser(responseData.billingUrl)
1120
1128
  setStep("code")
1121
1129
  return
1122
1130
  }
1123
1131
 
1124
- // Pending approval — retry with status message
1125
- const isPending = err.error === "pending" || err.error === "Session not yet approved" || err.status === "pending"
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(err.error || "Verification failed")
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 crypto from "crypto"
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 deployed = new Map<string, boolean>()
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 (deployed.get(context.instanceUrl)) return true
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
- if (!existing) {
231
- const svc = await client.post("/api/now/table/sys_ws_definition", {
232
- name: "Snow-Flow Script Executor",
233
- service_id: ENDPOINT_SERVICE_ID,
234
- short_description: "Synchronous script execution endpoint for Snow-Flow",
235
- active: true,
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
- const svcId = svc.data?.result?.sys_id
239
- if (!svcId) return false
246
+ const id = svc.data?.result?.sys_id
247
+ if (!id) return null
240
248
 
241
- const res = await client.post("/api/now/table/sys_ws_operation", {
242
- name: "Execute Script",
243
- web_service_definition: svcId,
244
- http_method: "POST",
245
- relative_path: ENDPOINT_PATH,
246
- operation_script: OPERATION_SCRIPT,
247
- active: true,
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
- if (!res.data?.result?.sys_id) return false
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
- const ping = await client
254
- .post(`/api/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`, {
255
- script: "'pong'",
256
- execution_id: "deploy_verify",
257
- })
258
- .catch(() => null)
289
+ if (ns) {
290
+ endpointCache.set(context.instanceUrl, { namespace: ns })
291
+ return true
292
+ }
259
293
 
260
- const ok = ping?.data?.result?.success === true
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(`/api/${ENDPOINT_SERVICE_ID}${ENDPOINT_PATH}`, {
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()}_${crypto.randomBytes(6).toString("hex")}`
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()}_${crypto.randomBytes(6).toString("hex")}`
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
 
@@ -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: ServiceNowClient,
70
- logger: MCPLogger,
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: ServiceNowClient, logger: MCPLogger) {
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 = ""
@@ -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: ServiceNowClient,
68
- logger: MCPLogger,
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: ServiceNowClient, logger: MCPLogger) {
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: ServiceNowClient,
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: ServiceNowClient, logger: MCPLogger) {
80
+ export async function createAuditRule(args: CreateAuditRuleArgs, client: any, logger: any) {
83
81
  try {
84
82
  logger.info("Creating Audit Rule...")
85
83
 
@@ -4,9 +4,22 @@
4
4
  * Creates a UI Policy Action (sys_ui_policy_action) that controls field
5
5
  * visibility, mandatory state, or read-only state when a UI policy's
6
6
  * conditions are met.
7
+ *
8
+ * ServiceNow field mapping:
9
+ * - visible/mandatory/disabled are STRING fields with values: "true", "false", "ignore"
10
+ * - "disabled" is the actual column name for "Read only" in the UI
11
+ * - "table" is auto-derived from the parent UI policy but must be sent for field validation
12
+ *
13
+ * Platform limitation:
14
+ * The "ui_policy" reference field on sys_ui_policy_action cannot be set via
15
+ * the REST Table API (POST/PUT/PATCH all silently ignore it). This is a known
16
+ * ServiceNow platform restriction for parent-child reference fields.
17
+ * Workaround: after Table API creation, a direct XML POST is attempted to set
18
+ * the ui_policy reference. If the XML POST also fails, the action is created
19
+ * without the reference — it can be linked manually in the UI.
7
20
  */
8
21
 
9
- import { MCPToolDefinition, ServiceNowContext, ToolResult } from "../../shared/types.js"
22
+ import type { MCPToolDefinition, ServiceNowContext, ToolResult } from "../../shared/types.js"
10
23
  import { getAuthenticatedClient } from "../../shared/auth.js"
11
24
  import { createSuccessResult, createErrorResult } from "../../shared/error-handler.js"
12
25
 
@@ -15,7 +28,7 @@ export const toolDefinition: MCPToolDefinition = {
15
28
  description:
16
29
  "Create a UI policy action to control field behavior (visible/mandatory/readonly) when a UI policy condition is met. Requires the parent UI policy sys_id and the target table name.",
17
30
  category: "development",
18
- subcategory: "platform",
31
+ subcategory: "ui-policies",
19
32
  use_cases: ["ui-policy-actions", "form-control", "ui-automation"],
20
33
  complexity: "intermediate",
21
34
  frequency: "medium",
@@ -31,7 +44,8 @@ export const toolDefinition: MCPToolDefinition = {
31
44
  },
32
45
  table: {
33
46
  type: "string",
34
- description: "Table name the UI policy applies to (e.g. 'incident', 'change_request'). Must match the table on the parent UI policy.",
47
+ description:
48
+ "Table name the UI policy applies to (e.g. 'incident', 'change_request'). Must match the table on the parent UI policy.",
35
49
  },
36
50
  field: {
37
51
  type: "string",
@@ -39,15 +53,17 @@ export const toolDefinition: MCPToolDefinition = {
39
53
  },
40
54
  visible: {
41
55
  type: "boolean",
42
- description: "Set field visibility. true = visible, false = hidden. Omit to leave unchanged.",
56
+ description: "Set field visibility. true = visible, false = hidden. Omit to leave unchanged ('ignore').",
43
57
  },
44
58
  mandatory: {
45
59
  type: "boolean",
46
- description: "Set field mandatory state. true = required, false = optional. Omit to leave unchanged.",
60
+ description:
61
+ "Set field mandatory state. true = required, false = optional. Omit to leave unchanged ('ignore').",
47
62
  },
48
63
  readonly: {
49
64
  type: "boolean",
50
- description: "Set field read-only state. true = read-only, false = editable. Omit to leave unchanged.",
65
+ description:
66
+ "Set field read-only state. true = read-only, false = editable. Omit to leave unchanged ('ignore').",
51
67
  },
52
68
  cleared: {
53
69
  type: "boolean",
@@ -58,50 +74,89 @@ export const toolDefinition: MCPToolDefinition = {
58
74
  },
59
75
  }
60
76
 
61
- export async function execute(args: any, context: ServiceNowContext): Promise<ToolResult> {
62
- const { ui_policy_sys_id, table, field, visible, mandatory, readonly, cleared } = args
77
+ function toActionValue(val: boolean | undefined): string {
78
+ if (val === undefined) return "ignore"
79
+ return val ? "true" : "false"
80
+ }
81
+
82
+ export async function execute(args: Record<string, unknown>, context: ServiceNowContext): Promise<ToolResult> {
83
+ const uid = args.ui_policy_sys_id as string
84
+ const table = args.table as string
85
+ const field = args.field as string
86
+ const visible = args.visible as boolean | undefined
87
+ const mandatory = args.mandatory as boolean | undefined
88
+ const readonly = args.readonly as boolean | undefined
89
+ const cleared = args.cleared as boolean | undefined
90
+
63
91
  try {
64
92
  const client = await getAuthenticatedClient(context)
65
93
 
66
- // Look up the parent UI policy to validate it exists and get its table
67
- const policyResponse = await client.get(
68
- "/api/now/table/sys_ui_policy/" + ui_policy_sys_id + "?sysparm_fields=sys_id,table,short_description",
94
+ const policyRes = await client.get(
95
+ "/api/now/table/sys_ui_policy/" + uid + "?sysparm_fields=sys_id,table,short_description",
69
96
  )
70
- const policy = policyResponse.data.result
97
+ const policy = policyRes.data.result
71
98
  if (!policy || !policy.sys_id) {
72
- return createErrorResult("UI Policy not found with sys_id: " + ui_policy_sys_id)
99
+ return createErrorResult("UI Policy not found with sys_id: " + uid)
73
100
  }
74
101
 
75
- const actionData: any = {
76
- ui_policy: ui_policy_sys_id,
102
+ const payload: Record<string, string | boolean> = {
103
+ ui_policy: uid,
77
104
  table: table,
78
105
  field: field,
79
- visible: visible !== undefined ? visible : true,
80
- mandatory: mandatory !== undefined ? mandatory : false,
81
- readonly: readonly !== undefined ? readonly : false,
82
- cleared: cleared !== undefined ? cleared : false,
106
+ visible: toActionValue(visible),
107
+ mandatory: toActionValue(mandatory),
108
+ disabled: toActionValue(readonly),
109
+ cleared: cleared === true,
83
110
  }
84
111
 
85
- const response = await client.post("/api/now/table/sys_ui_policy_action", actionData)
112
+ const response = await client.post("/api/now/table/sys_ui_policy_action", payload)
86
113
  const action = response.data.result
114
+ const actionSysId = action.sys_id?.value || action.sys_id
115
+
116
+ const linked = await (async () => {
117
+ try {
118
+ const xmlBody =
119
+ "<record>" + "<sys_id>" + actionSysId + "</sys_id>" + "<ui_policy>" + uid + "</ui_policy>" + "</record>"
120
+ await client.post("/sys_ui_policy_action.do?XML&sys_id=" + actionSysId, xmlBody, {
121
+ headers: { "Content-Type": "application/xml" },
122
+ })
123
+
124
+ const verify = await client.get(
125
+ "/api/now/table/sys_ui_policy_action/" + actionSysId + "?sysparm_fields=ui_policy",
126
+ )
127
+ const ref = verify.data.result?.ui_policy
128
+ const val = typeof ref === "object" && ref !== null ? ref.value : ref
129
+ return !!val && val !== ""
130
+ } catch (_e) {
131
+ return false
132
+ }
133
+ })()
134
+
135
+ const refVal = action.ui_policy
136
+ const resolvedRef = typeof refVal === "object" && refVal !== null ? refVal.value : refVal
87
137
 
88
138
  return createSuccessResult({
89
139
  created: true,
90
140
  action: {
91
- sys_id: action.sys_id,
92
- ui_policy: ui_policy_sys_id,
93
- table: table,
94
- field: action.field,
95
- visible: action.visible,
96
- mandatory: action.mandatory,
97
- readonly: action.readonly,
98
- cleared: action.cleared,
141
+ sys_id: actionSysId,
142
+ ui_policy: linked ? uid : resolvedRef || "",
143
+ ui_policy_linked: linked,
144
+ table: action.table?.value || action.table,
145
+ field: action.field?.value || action.field,
146
+ visible: action.visible?.value || action.visible,
147
+ mandatory: action.mandatory?.value || action.mandatory,
148
+ disabled: action.disabled?.value || action.disabled,
149
+ cleared: action.cleared?.value || action.cleared,
99
150
  },
151
+ warning: linked
152
+ ? undefined
153
+ : "The ui_policy reference field could not be set via the REST API (ServiceNow platform limitation). The action was created but is not linked to the parent UI policy. Link it manually in the ServiceNow UI.",
100
154
  })
101
- } catch (error: any) {
102
- return createErrorResult(error.message)
155
+ } catch (error: unknown) {
156
+ const msg = error instanceof Error ? error.message : String(error)
157
+ return createErrorResult(msg)
103
158
  }
104
159
  }
105
160
 
106
- export const version = "1.0.0"
161
+ export const version = "1.1.0"
107
162
  export const author = "Snow-Flow SDK Migration"
@@ -4,7 +4,7 @@
4
4
  * Implements MCP prompts protocol for reusable prompt templates and workflows
5
5
  */
6
6
 
7
- import { Logger } from "../utils/logger.js"
7
+ import { mcpDebug } from "./mcp-debug.js"
8
8
 
9
9
  /**
10
10
  * Prompt argument definition
@@ -85,13 +85,13 @@ export type PromptHandler = (args: Record<string, string>) => Promise<MCPPromptR
85
85
  * Manages prompt templates, registration, and execution
86
86
  */
87
87
  export class MCPPromptManager {
88
- private logger: Logger
88
+ private prefix: string
89
89
  private promptRegistry: Map<string, MCPPrompt> = new Map()
90
90
  private promptHandlers: Map<string, PromptHandler> = new Map()
91
91
  private categories: PromptCategory[] = []
92
92
 
93
93
  constructor(serverName: string = "mcp-server") {
94
- this.logger = new Logger(`PromptManager:${serverName}`)
94
+ this.prefix = `[PromptManager:${serverName}]`
95
95
  this.initializeDefaultPrompts()
96
96
  }
97
97
 
@@ -109,7 +109,7 @@ export class MCPPromptManager {
109
109
  registerPrompt(prompt: MCPPrompt, handler: PromptHandler): void {
110
110
  this.promptRegistry.set(prompt.name, prompt)
111
111
  this.promptHandlers.set(prompt.name, handler)
112
- this.logger.debug(`Registered prompt: ${prompt.name}`)
112
+ mcpDebug(`Registered prompt: ${prompt.name}`)
113
113
  }
114
114
 
115
115
  /**
@@ -119,7 +119,7 @@ export class MCPPromptManager {
119
119
  const deleted = this.promptRegistry.delete(name)
120
120
  this.promptHandlers.delete(name)
121
121
  if (deleted) {
122
- this.logger.debug(`Unregistered prompt: ${name}`)
122
+ mcpDebug(`Unregistered prompt: ${name}`)
123
123
  }
124
124
  return deleted
125
125
  }
@@ -161,7 +161,7 @@ export class MCPPromptManager {
161
161
  }
162
162
  }
163
163
 
164
- this.logger.debug(`Executing prompt: ${name}`, { args })
164
+ mcpDebug(`Executing prompt: ${name}`, { args })
165
165
  return await handler(args)
166
166
  }
167
167
 
@@ -218,6 +218,6 @@ export class MCPPromptManager {
218
218
  this.promptRegistry.clear()
219
219
  this.promptHandlers.clear()
220
220
  this.categories = []
221
- this.logger.debug("All prompts cleared")
221
+ mcpDebug("All prompts cleared")
222
222
  }
223
223
  }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "lib": ["ESNext"],
5
+ "target": "ESNext",
6
+ "module": "Preserve",
7
+ "moduleDetection": "force",
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "noEmit": true,
11
+ "skipLibCheck": true,
12
+ "types": ["bun-types"],
13
+ "noUncheckedIndexedAccess": false,
14
+ "customConditions": ["browser"],
15
+ "paths": {
16
+ "@/*": ["./src/*"]
17
+ }
18
+ },
19
+ "include": ["src/servicenow/**/*"]
20
+ }