snow-flow 4.5.51 → 4.5.53

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/CLAUDE.md CHANGED
@@ -6,14 +6,26 @@
6
6
 
7
7
  **❌ INFINITE LOOP (PROHIBITED):**
8
8
  ```
9
- Task("Create configurable workspace")
10
- Task("Create configurable workspace")
11
- Task("Create configurable workspace") // CAUSES INFINITE LOOP!
9
+ Task("UI Builder Tools Tester", "Test UI Builder tools");
10
+ Task("UI Builder Tools Tester", "Test UI Builder tools"); // ← DUPLICATE AGENT TYPE!
11
+ Task("Workspace Tools Tester", "Test workspace tools");
12
+ Task("Workspace Tools Tester", "Test workspace tools"); // ← CAUSES INFINITE LOOP!
13
+
14
+ // This pattern causes MCP server spam:
15
+ // • Task(UI Builder Tools Tester) → snow_validate_uib_page_structure (repeated 100x)
16
+ // • Task(Workspace Tools Tester) → snow_execute_script_with_output (repeated 100x)
12
17
  ```
13
18
 
14
19
  **✅ CORRECT (Single Agent):**
15
- ```
16
- Task("workspace-specialist", "Create ONE Configurable Agent Workspace named 'IT Support Hub' using snow_create_workspace with UX App architecture. Verify creation and store sys_id in Memory.")
20
+ ```
21
+ // UNIQUE agent names prevent loops:
22
+ Task("workspace-architect", "Create ONE UX workspace for IT support using snow_create_complete_workspace. Store all sys_ids in Memory.");
23
+ Task("ui-specialist", "Design UI components AFTER workspace-architect completes. Use Memory to get workspace sys_ids.");
24
+ Task("testing-validator", "Test workspace functionality AFTER ui-specialist completes. No duplicate testing!");
25
+
26
+ // NEVER use generic names like:
27
+ // Task("Tester", ...) - TOO GENERIC, CAUSES LOOPS!
28
+ // Task("UI Builder Tools Tester", ...) - EXACTLY what caused the infinite loop!
17
29
  ```
18
30
 
19
31
  **🎯 Anti-Loop Rules:**
package/dist/cli.js CHANGED
@@ -643,6 +643,31 @@ function buildQueenAgentPrompt(objective, taskAnalysis, options, isAuthenticated
643
643
  options.sharedMemory || options.progressMonitoring;
644
644
  const prompt = `# 👑 Snow-Flow Queen Agent Orchestration
645
645
 
646
+ ## 🚨 CRITICAL: PREVENT INFINITE LOOPS - READ FIRST!
647
+
648
+ **NEVER SPAWN DUPLICATE AGENTS!** This causes infinite loops that spam MCP servers and crash Codespaces!
649
+
650
+ **❌ INFINITE LOOP PATTERN (PROHIBITED):**
651
+ \`\`\`
652
+ Task(\"UI Builder Tools Tester\", \"Test UI Builder tools\");
653
+ Task(\"UI Builder Tools Tester\", \"Test UI Builder tools\"); // ← DUPLICATE AGENT TYPE!
654
+ Task(\"Workspace Tools Tester\", \"Test workspace tools\");
655
+ Task(\"Workspace Tools Tester\", \"Test workspace tools\"); // ← INFINITE LOOP!
656
+ \`\`\`
657
+
658
+ **✅ CORRECT PATTERN (REQUIRED):**
659
+ \`\`\`
660
+ Task(\"workspace-architect\", \"Create ONE UX workspace using snow_create_complete_workspace\");
661
+ Task(\"ui-designer\", \"Design UI components AFTER workspace is created\");
662
+ Task(\"validator\", \"Test AFTER both previous agents complete\");
663
+ \`\`\`
664
+
665
+ **GOLDEN RULES:**
666
+ 1. **ONE agent per task type maximum**
667
+ 2. **UNIQUE agent names** (not generic \"Tester\")
668
+ 3. **SEQUENTIAL spawning** - wait for completion
669
+ 4. **CHECK Memory** for existing agents first
670
+
646
671
  ## 🎯 Mission Brief
647
672
  You are the Queen Agent, master coordinator of the Snow-Flow hive-mind. Your mission is to orchestrate a swarm of specialized agents to complete the following ServiceNow development objective:
648
673
 
@@ -838,29 +863,68 @@ TodoWrite([
838
863
  ]);
839
864
  \`\`\`
840
865
 
841
- ### 4. Agent Spawning Strategy
842
- Based on the task analysis, spawn ${taskAnalysis.estimatedAgentCount} agents in smart batches:
866
+ ### 4. Agent Spawning Strategy - 🚨 ANTI-LOOP PROTECTION 🚨
867
+
868
+ **CRITICAL: NO DUPLICATE AGENTS! ONLY SPAWN EACH AGENT TYPE ONCE!**
843
869
 
844
- **Dynamic Agent Discovery & Spawning (Use Snow-Flow MCP Tools):**
845
- 1. **Initialize Swarm**: \`swarm_init({ topology: 'hierarchical', maxAgents: ${parseInt(options.maxAgents)} })\`
846
- 2. **Discover Agents Dynamically**: \`agent_discover({ task_analysis: ${JSON.stringify(taskAnalysis)}, required_capabilities: [], context: { max_agents: ${parseInt(options.maxAgents)}, include_new_types: true } })\`
847
- 3. **Spawn Discovered Agents**: Use \`agent_spawn({ type: 'agent_type_from_discovery', name: 'Agent Name', capabilities: ['discovered_capabilities'] })\` for each discovered agent
848
- 4. **Coordination**: \`task_orchestrate({ task: '${objective}', strategy: 'adaptive' })\`
870
+ **✅ CORRECT (Single Agents Only):**
871
+ 1. **Initialize Swarm ONCE**: \`swarm_init({ topology: 'hierarchical', maxAgents: ${parseInt(options.maxAgents)} })\`
872
+ 2. **Spawn ${taskAnalysis.estimatedAgentCount} DIFFERENT agents**:
873
+ Spawn ONE agent of each required type based on the objective:
849
874
 
850
- **IMPORTANT**: Do NOT use hardcoded agent types like 'widget-creator', 'specialist' etc. Let \`agent_discover\` determine the optimal agent types for this specific task!
875
+ **${taskAnalysis.taskType} requires these UNIQUE agents:**
876
+ - **ONE researcher**: \`Task(\"researcher\", \"Research ServiceNow requirements for: ${objective}\")\`
877
+ - **ONE ${taskAnalysis.primaryAgent}**: \`Task(\"${taskAnalysis.primaryAgent}\", \"Implement main solution for: ${objective}\")\`
878
+ - **ONE tester**: \`Task(\"tester\", \"Test and validate solution for: ${objective}\")\`
851
879
 
852
- ### 5. Memory Coordination Pattern
853
- All agents MUST use this simple memory coordination:
880
+ **🚨 CRITICAL ANTI-LOOP RULES:**
881
+ - **NEVER spawn multiple agents of the same type**
882
+ - **NEVER spawn \"UI Builder Tools Tester\" multiple times**
883
+ - **NEVER spawn \"Workspace Tools Tester\" multiple times**
884
+ - **WAIT for agent completion** before spawning related agents
885
+ - **CHECK Memory** for existing agents before spawning new ones
886
+
887
+ **❌ PROHIBITED PATTERNS:**
888
+ \`\`\`
889
+ // DON'T DO THIS - CAUSES INFINITE LOOPS:
890
+ Task(\"UI Builder Tools Tester\", \"Test UI Builder tools\");
891
+ Task(\"UI Builder Tools Tester\", \"Test UI Builder tools\"); // ← DUPLICATE!
892
+ Task(\"UI Builder Tools Tester\", \"Test UI Builder tools\"); // ← INFINITE LOOP!
893
+ \`\`\`
894
+
895
+ **✅ CORRECT PATTERNS:**
896
+ \`\`\`
897
+ // DO THIS - SINGLE AGENTS WITH SPECIFIC TASKS:
898
+ Task(\"ui-builder-specialist\", \"Create specific UI Builder page for incident management\");
899
+ Task(\"workspace-architect\", \"Design UX workspace structure for IT support team\");
900
+ Task(\"testing-specialist\", \"Validate workspace functionality and report results\");
901
+ \`\`\`
902
+
903
+ ### 5. Memory Coordination Pattern with Loop Detection
904
+ All agents MUST use this memory coordination WITH loop prevention:
854
905
 
855
906
  \`\`\`javascript
856
- // Agent initialization
907
+ // STEP 1: Check if agent type already exists (PREVENT LOOPS!)
908
+ const existingAgents = Memory.get('active_agents') || [];
909
+ const agentType = 'ui-builder-specialist';
910
+
911
+ if (existingAgents.includes(agentType)) {
912
+ console.log('Agent type already active - SKIPPING to prevent infinite loop');
913
+ return; // DON'T spawn duplicate agents!
914
+ }
915
+
916
+ // STEP 2: Register agent as active
857
917
  const agentId = \`agent_\${agentType}_\${sessionId}\`;
918
+ existingAgents.push(agentType);
919
+ Memory.store('active_agents', JSON.stringify(existingAgents));
858
920
 
859
- // Agent stores progress
921
+ // STEP 3: Agent stores progress
860
922
  Memory.store(\`\${agentId}_progress\`, JSON.stringify({
923
+ agent_type: agentType,
861
924
  status: "working",
862
925
  current_task: "description of current work",
863
926
  completion_percentage: 45,
927
+ spawned_at: new Date().toISOString(),
864
928
  last_update: new Date().toISOString()
865
929
  }));
866
930
 
@@ -27,6 +27,30 @@ class ServiceNowFlowWorkspaceMobileMCP {
27
27
  this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowFlowWorkspaceMobileMCP');
28
28
  this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
29
29
  this.setupHandlers();
30
+ this.setupSimpleStability();
31
+ }
32
+ /**
33
+ * Simple stability setup - no complex wrappers
34
+ */
35
+ setupSimpleStability() {
36
+ // Graceful shutdown on process signals
37
+ process.on('SIGTERM', () => {
38
+ this.logger.info('🛑 Received SIGTERM - shutting down MCP server gracefully');
39
+ process.exit(0);
40
+ });
41
+ process.on('SIGINT', () => {
42
+ this.logger.info('🛑 Received SIGINT - shutting down MCP server gracefully');
43
+ process.exit(0);
44
+ });
45
+ // Handle uncaught errors (prevents crashes)
46
+ process.on('uncaughtException', (error) => {
47
+ this.logger.error('💥 Uncaught exception in MCP server:', error);
48
+ // Don't exit - just log and continue
49
+ });
50
+ process.on('unhandledRejection', (reason) => {
51
+ this.logger.error('💥 Unhandled promise rejection in MCP server:', reason);
52
+ // Don't exit - just log and continue
53
+ });
30
54
  }
31
55
  setupHandlers() {
32
56
  this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
@@ -263,35 +287,6 @@ class ServiceNowFlowWorkspaceMobileMCP {
263
287
  required: ['workspace_sys_id', 'workspace_type']
264
288
  }
265
289
  },
266
- // COMPREHENSIVE TOOL HEALTH CHECKING
267
- {
268
- name: 'snow_test_all_workspace_tools',
269
- description: 'Test all workspace and UI Builder tools to check availability, permissions, and functionality. Provides comprehensive status report with detailed feedback.',
270
- inputSchema: {
271
- type: 'object',
272
- properties: {
273
- include_ui_builder: { type: 'boolean', default: true, description: 'Test UI Builder tools' },
274
- include_workspace: { type: 'boolean', default: true, description: 'Test workspace creation tools' },
275
- include_mobile: { type: 'boolean', default: true, description: 'Test mobile tools' },
276
- include_flow: { type: 'boolean', default: true, description: 'Test flow tools' },
277
- detailed_errors: { type: 'boolean', default: true, description: 'Include detailed error information' }
278
- }
279
- }
280
- },
281
- {
282
- name: 'snow_check_plugin_availability',
283
- description: 'Check availability and licensing status of all ServiceNow plugins required for workspace and UI Builder functionality.',
284
- inputSchema: {
285
- type: 'object',
286
- properties: {
287
- check_ui_builder: { type: 'boolean', default: true, description: 'Check UI Builder plugin' },
288
- check_uxf: { type: 'boolean', default: true, description: 'Check Now Experience Framework' },
289
- check_agent_workspace: { type: 'boolean', default: true, description: 'Check Agent Workspace plugin' },
290
- check_mobile: { type: 'boolean', default: true, description: 'Check Mobile Publishing' },
291
- include_recommendations: { type: 'boolean', default: true, description: 'Include setup recommendations' }
292
- }
293
- }
294
- },
295
290
  // Mobile Tools
296
291
  {
297
292
  name: 'snow_configure_mobile_app',
@@ -851,12 +846,6 @@ class ServiceNowFlowWorkspaceMobileMCP {
851
846
  case 'snow_validate_workspace_configuration':
852
847
  result = await this.validateWorkspaceConfiguration(args);
853
848
  break;
854
- case 'snow_test_all_workspace_tools':
855
- result = await this.testAllWorkspaceTools(args);
856
- break;
857
- case 'snow_check_plugin_availability':
858
- result = await this.checkPluginAvailability(args);
859
- break;
860
849
  // Mobile
861
850
  case 'snow_configure_mobile_app':
862
851
  result = await this.configureMobileApp(args);
@@ -1412,59 +1401,20 @@ ${executionList}
1412
1401
  }
1413
1402
  throw new Error(`Failed to configure mobile app: ${response.error}`);
1414
1403
  }
1415
- // VERIFICATION: Confirm mobile app was configured (fix sys_id access)
1416
- const sys_id = response.data?.result?.sys_id || response.data?.sys_id;
1417
- if (!sys_id) {
1418
- return {
1419
- success: false,
1420
- error: 'Mobile app configuration succeeded but no sys_id returned in response',
1421
- debug_info: {
1422
- has_data: !!response.data,
1423
- has_result: !!(response.data && response.data.result),
1424
- response_structure: typeof response.data
1425
- },
1426
- suggestion: 'ServiceNow API response format may be different than expected'
1427
- };
1428
- }
1429
- // Note: Mobile app config table name may vary - try common variations
1430
- let verification = await this.client.getRecord('sys_mobile_app_config', sys_id);
1431
- if (!verification.success) {
1432
- verification = await this.client.getRecord('sys_mobile_application', sys_id);
1433
- }
1434
- if (!verification.success) {
1435
- verification = await this.client.getRecord('sys_push_app', sys_id);
1436
- }
1437
- if (!verification.success) {
1438
- return {
1439
- success: false,
1440
- error: 'Mobile app configuration reported success but record not found in sys_mobile_application_config table',
1441
- suggestion: 'Mobile app configuration may have been rolled back due to validation errors',
1442
- verification_failed: true
1443
- };
1444
- }
1445
- this.logger.info(`✅ Mobile app configured and verified: ${sys_id}`);
1446
1404
  return {
1447
- success: true,
1448
- verified: true,
1449
- mobile_app_sys_id: sys_id,
1450
- app_name: args.app_name,
1451
- authentication: args.authentication || 'oauth',
1452
- modules_count: args.enabled_modules ? args.enabled_modules.length : 0,
1453
- offline_tables_count: args.offline_tables ? args.offline_tables.length : 0,
1454
- push_enabled: args.push_enabled !== false,
1455
- created_at: new Date().toISOString(),
1456
- message: `✅ Mobile app '${args.app_name}' configured and verified successfully`,
1457
- detailed_confirmation: {
1458
- operation: 'CONFIGURE Mobile App',
1459
- sys_id: sys_id,
1460
- app_name: args.app_name,
1461
- authentication_method: args.authentication || 'oauth',
1462
- enabled_modules: args.enabled_modules || [],
1463
- offline_tables: args.offline_tables || [],
1464
- push_notifications: args.push_enabled !== false,
1465
- verified_in_table: 'sys_mobile_application_config',
1466
- verification_timestamp: new Date().toISOString()
1467
- }
1405
+ content: [{
1406
+ type: 'text',
1407
+ text: `✅ Mobile App configured!
1408
+
1409
+ 📱 **${args.app_name}**
1410
+ 🆔 sys_id: ${response.data.sys_id}
1411
+ 🔐 Authentication: ${args.authentication || 'oauth'}
1412
+ 📦 Modules: ${args.enabled_modules ? args.enabled_modules.length : 0}
1413
+ 💾 Offline Tables: ${args.offline_tables ? args.offline_tables.length : 0}
1414
+ 🔔 Push Notifications: ${args.push_enabled !== false ? 'Enabled' : 'Disabled'}
1415
+
1416
+ Mobile app configuration saved!`
1417
+ }]
1468
1418
  };
1469
1419
  }
1470
1420
  catch (error) {
@@ -1497,58 +1447,20 @@ ${executionList}
1497
1447
  if (!response.success) {
1498
1448
  throw new Error(`Failed to create mobile layout: ${response.error}`);
1499
1449
  }
1500
- // VERIFICATION: Confirm mobile layout was created (fix sys_id access)
1501
- const sys_id = response.data?.result?.sys_id || response.data?.sys_id;
1502
- if (!sys_id) {
1503
- return {
1504
- success: false,
1505
- error: 'Mobile layout creation succeeded but no sys_id returned in response',
1506
- debug_info: {
1507
- has_data: !!response.data,
1508
- has_result: !!(response.data && response.data.result),
1509
- response_structure: typeof response.data
1510
- },
1511
- suggestion: 'ServiceNow API response format may be different than expected'
1512
- };
1513
- }
1514
- // Note: Mobile layout table name may vary - try common variations
1515
- let verification = await this.client.getRecord('sys_mobile_form_layout', sys_id);
1516
- if (!verification.success) {
1517
- verification = await this.client.getRecord('sys_mobile_list_layout', sys_id);
1518
- }
1519
- if (!verification.success) {
1520
- verification = await this.client.getRecord('sys_ui_form_section', sys_id);
1521
- }
1522
- if (!verification.success) {
1523
- return {
1524
- success: false,
1525
- error: 'Mobile layout creation reported success but record not found in sys_mobile_layout table',
1526
- suggestion: 'Mobile layout creation may have been rolled back due to validation errors',
1527
- verification_failed: true
1528
- };
1529
- }
1530
- this.logger.info(`✅ Mobile layout created and verified: ${sys_id}`);
1531
1450
  return {
1532
- success: true,
1533
- verified: true,
1534
- mobile_layout_sys_id: sys_id,
1535
- layout_name: args.name,
1536
- layout_table: args.table,
1537
- layout_type: args.type,
1538
- fields_count: args.fields ? args.fields.length : 0,
1539
- related_lists_count: args.related_lists ? args.related_lists.length : 0,
1540
- created_at: new Date().toISOString(),
1541
- message: `✅ Mobile layout '${args.name}' created and verified successfully`,
1542
- detailed_confirmation: {
1543
- operation: 'CREATE Mobile Layout',
1544
- sys_id: sys_id,
1545
- name: args.name,
1546
- table: args.table,
1547
- type: args.type,
1548
- fields: args.fields || [],
1549
- verified_in_table: 'sys_mobile_layout',
1550
- verification_timestamp: new Date().toISOString()
1551
- }
1451
+ content: [{
1452
+ type: 'text',
1453
+ text: `✅ Mobile Layout created!
1454
+
1455
+ 📱 **${args.name}**
1456
+ 🆔 sys_id: ${response.data.sys_id}
1457
+ 📋 Table: ${args.table}
1458
+ 📊 Type: ${args.type}
1459
+ 📝 Fields: ${args.fields ? args.fields.length : 'Default'}
1460
+ 🔗 Related Lists: ${args.related_lists ? args.related_lists.length : 0}
1461
+
1462
+ Mobile layout configured!`
1463
+ }]
1552
1464
  };
1553
1465
  }
1554
1466
  catch (error) {
@@ -1914,30 +1826,9 @@ ${configList}${layoutsText}${offlineText}
1914
1826
  const query = conditions.join('^');
1915
1827
  const pagesResponse = await this.client.searchRecords('sys_ux_page', query, args.limit || 50);
1916
1828
  if (!pagesResponse.success) {
1917
- return {
1918
- success: false,
1919
- error: `Failed to discover UI Builder pages: ${pagesResponse.error}`,
1920
- suggestion: 'UI Builder plugin may not be installed. Check ServiceNow Store for UI Builder plugin.',
1921
- plugin_required: 'UI Builder',
1922
- table_tested: 'sys_ux_page'
1923
- };
1924
- }
1925
- const pages = pagesResponse.data.result || [];
1926
- // Handle no results case
1927
- if (pages.length === 0) {
1928
- return {
1929
- success: true,
1930
- pages: [],
1931
- count: 0,
1932
- message: '📝 No UI Builder pages found',
1933
- explanation: 'This could mean: 1) No pages exist yet, 2) UI Builder plugin not installed, 3) Insufficient permissions to view pages',
1934
- suggestions: [
1935
- 'Create your first UI Builder page using snow_create_uib_page',
1936
- 'Check if UI Builder plugin is installed and activated',
1937
- 'Verify you have ui_builder_user or ui_builder_admin roles'
1938
- ]
1939
- };
1829
+ throw new Error(`Failed to discover UI Builder pages: ${pagesResponse.error}`);
1940
1830
  }
1831
+ const pages = pagesResponse.data.result;
1941
1832
  // Enrich with additional data if requested
1942
1833
  for (const page of pages) {
1943
1834
  if (args.include_routing) {
@@ -1956,29 +1847,13 @@ ${configList}${layoutsText}${offlineText}
1956
1847
  this.logger.info(`✅ Found ${pages.length} UI Builder pages`);
1957
1848
  return {
1958
1849
  success: true,
1959
- verified: true,
1960
1850
  pages: pages,
1961
- count: pages.length,
1962
- query_used: query || 'No filter',
1963
- message: `✅ Successfully discovered ${pages.length} UI Builder pages`,
1964
- detailed_confirmation: {
1965
- operation: 'DISCOVER UI Builder Pages',
1966
- table_searched: 'sys_ux_page',
1967
- results_count: pages.length,
1968
- query_conditions: conditions.join(', ') || 'No conditions',
1969
- search_timestamp: new Date().toISOString()
1970
- }
1851
+ count: pages.length
1971
1852
  };
1972
1853
  }
1973
1854
  catch (error) {
1974
1855
  this.logger.error('Failed to discover UI Builder pages:', error);
1975
- return {
1976
- success: false,
1977
- error: `Failed to discover UI Builder pages: ${error}`,
1978
- suggestion: 'UI Builder plugin may not be installed or you may lack permissions',
1979
- table_tested: 'sys_ux_page',
1980
- operation_attempted: 'DISCOVER UI Builder Pages'
1981
- };
1856
+ throw error;
1982
1857
  }
1983
1858
  }
1984
1859
  /**
@@ -2019,34 +1894,12 @@ ${configList}${layoutsText}${offlineText}
2019
1894
  await this.client.deleteRecord('sys_ux_lib_source_script', sourceResponse.data.sys_id);
2020
1895
  throw new Error(`Failed to create component: ${componentResponse.error}`);
2021
1896
  }
2022
- // VERIFICATION: Confirm both records were created
2023
- const componentVerification = await this.client.getRecord('sys_ux_lib_component', componentResponse.data.result.sys_id);
2024
- const sourceVerification = await this.client.getRecord('sys_ux_lib_source_script', sourceResponse.data.result.sys_id);
2025
- if (!componentVerification.success || !sourceVerification.success) {
2026
- return {
2027
- success: false,
2028
- error: 'Component creation reported success but records not found in tables',
2029
- suggestion: 'Component creation may have been rolled back due to validation errors',
2030
- verification_failed: true
2031
- };
2032
- }
2033
- this.logger.info(`✅ UI Builder component created and verified: ${componentResponse.data.result.sys_id}`);
1897
+ this.logger.info('✅ UI Builder component created successfully');
2034
1898
  return {
2035
1899
  success: true,
2036
- verified: true,
2037
- component_sys_id: componentResponse.data.result.sys_id,
2038
- source_script_sys_id: sourceResponse.data.result.sys_id,
2039
- component_name: args.name,
2040
- category: args.category || 'custom',
2041
- created_at: new Date().toISOString(),
2042
- message: `✅ Custom UI Builder component '${args.name}' created and verified successfully`,
2043
- detailed_confirmation: {
2044
- operation: 'CREATE UI Builder Component',
2045
- component_sys_id: componentResponse.data.result.sys_id,
2046
- source_script_sys_id: sourceResponse.data.result.sys_id,
2047
- verified_in_tables: ['sys_ux_lib_component', 'sys_ux_lib_source_script'],
2048
- verification_timestamp: new Date().toISOString()
2049
- }
1900
+ component: componentResponse.data,
1901
+ source_script: sourceResponse.data,
1902
+ message: `Custom UI Builder component '${args.name}' created successfully`
2050
1903
  };
2051
1904
  }
2052
1905
  catch (error) {
@@ -2125,31 +1978,9 @@ ${configList}${layoutsText}${offlineText}
2125
1978
  const query = conditions.join('^');
2126
1979
  const componentsResponse = await this.client.searchRecords('sys_ux_lib_component', query, args.limit || 100);
2127
1980
  if (!componentsResponse.success) {
2128
- return {
2129
- success: false,
2130
- error: `Failed to discover UI Builder components: ${componentsResponse.error}`,
2131
- suggestion: 'UI Builder plugin may not be installed. Check ServiceNow Store for UI Builder plugin.',
2132
- plugin_required: 'UI Builder',
2133
- table_tested: 'sys_ux_lib_component'
2134
- };
2135
- }
2136
- const components = componentsResponse.data.result || [];
2137
- // Handle no results case
2138
- if (components.length === 0) {
2139
- return {
2140
- success: true,
2141
- components: [],
2142
- count: 0,
2143
- message: '📝 No UI Builder components found',
2144
- explanation: 'This could mean: 1) No custom components exist, 2) UI Builder plugin not installed, 3) Insufficient permissions',
2145
- query_used: query || 'No filter',
2146
- suggestions: [
2147
- 'Create your first custom component using snow_create_uib_component',
2148
- 'Check built-in components by removing custom_only filter',
2149
- 'Verify UI Builder plugin is installed and you have proper permissions'
2150
- ]
2151
- };
1981
+ throw new Error(`Failed to discover components: ${componentsResponse.error}`);
2152
1982
  }
1983
+ const components = componentsResponse.data.result;
2153
1984
  // Enrich with additional data if requested
2154
1985
  for (const component of components) {
2155
1986
  if (args.include_source && component.source_script) {
@@ -2167,35 +1998,13 @@ ${configList}${layoutsText}${offlineText}
2167
1998
  this.logger.info(`✅ Found ${components.length} UI Builder components`);
2168
1999
  return {
2169
2000
  success: true,
2170
- verified: true,
2171
2001
  components: components,
2172
- count: components.length,
2173
- query_used: query || 'No filter',
2174
- categories_found: [...new Set(components.map(c => c.category))],
2175
- message: `✅ Successfully discovered ${components.length} UI Builder components`,
2176
- detailed_confirmation: {
2177
- operation: 'DISCOVER UI Builder Components',
2178
- table_searched: 'sys_ux_lib_component',
2179
- results_count: components.length,
2180
- query_conditions: conditions.join(', ') || 'No conditions',
2181
- enrichment_options: {
2182
- source_included: !!args.include_source,
2183
- usage_stats_included: !!args.include_usage_stats,
2184
- dependencies_included: !!args.include_dependencies
2185
- },
2186
- search_timestamp: new Date().toISOString()
2187
- }
2002
+ count: components.length
2188
2003
  };
2189
2004
  }
2190
2005
  catch (error) {
2191
2006
  this.logger.error('Failed to discover UI Builder components:', error);
2192
- return {
2193
- success: false,
2194
- error: `Failed to discover UI Builder components: ${error}`,
2195
- suggestion: 'UI Builder plugin may not be installed or you may lack permissions',
2196
- table_tested: 'sys_ux_lib_component',
2197
- operation_attempted: 'DISCOVER UI Builder Components'
2198
- };
2007
+ throw error;
2199
2008
  }
2200
2009
  }
2201
2010
  /**
@@ -2257,17 +2066,6 @@ ${configList}${layoutsText}${offlineText}
2257
2066
  async createUIBDataBroker(args) {
2258
2067
  try {
2259
2068
  this.logger.info(`🔗 Creating UI Builder data broker: ${args.name}`);
2260
- // FIRST: Check if UI Builder is available
2261
- const uiBuilderCheck = await this.client.searchRecords('sys_ux_data_broker', '', 1);
2262
- if (!uiBuilderCheck.success) {
2263
- return {
2264
- success: false,
2265
- error: 'UI Builder data broker table (sys_ux_data_broker) not accessible',
2266
- suggestion: 'UI Builder plugin may not be installed or you may lack ui_builder_admin permissions',
2267
- plugin_required: 'UI Builder',
2268
- table_tested: 'sys_ux_data_broker'
2269
- };
2270
- }
2271
2069
  const brokerData = {
2272
2070
  name: args.name,
2273
2071
  label: args.label,
@@ -2285,55 +2083,13 @@ ${configList}${layoutsText}${offlineText}
2285
2083
  };
2286
2084
  const response = await this.client.createRecord('sys_ux_data_broker', brokerData);
2287
2085
  if (!response.success) {
2288
- return {
2289
- success: false,
2290
- error: `Failed to create data broker: ${response.error || response}`,
2291
- suggestion: this.getErrorSuggestion(String(response.error || response)),
2292
- operation_attempted: 'CREATE sys_ux_data_broker',
2293
- broker_data: brokerData
2294
- };
2086
+ throw new Error(`Failed to create data broker: ${response.error}`);
2295
2087
  }
2296
- // VERIFICATION: Confirm data broker was created (fix sys_id access)
2297
- const sys_id = response.data?.result?.sys_id || response.data?.sys_id;
2298
- if (!sys_id) {
2299
- return {
2300
- success: false,
2301
- error: 'Data broker creation succeeded but no sys_id returned in response',
2302
- debug_info: {
2303
- has_data: !!response.data,
2304
- has_result: !!(response.data && response.data.result),
2305
- response_structure: typeof response.data
2306
- },
2307
- suggestion: 'ServiceNow API response format may be different than expected'
2308
- };
2309
- }
2310
- const verification = await this.client.getRecord('sys_ux_data_broker', sys_id);
2311
- if (!verification.success) {
2312
- return {
2313
- success: false,
2314
- error: 'Data broker creation reported success but record not found in sys_ux_data_broker table',
2315
- suggestion: 'Data broker creation may have been rolled back due to validation errors',
2316
- verification_failed: true
2317
- };
2318
- }
2319
- this.logger.info(`✅ UI Builder data broker created and verified: ${sys_id}`);
2088
+ this.logger.info('✅ UI Builder data broker created successfully');
2320
2089
  return {
2321
2090
  success: true,
2322
- verified: true,
2323
- data_broker_sys_id: sys_id,
2324
- broker_name: args.name,
2325
- broker_type: args.type || 'table',
2326
- target_table: args.table || 'N/A',
2327
- created_at: new Date().toISOString(),
2328
- message: `✅ Data broker '${args.name}' created and verified successfully`,
2329
- detailed_confirmation: {
2330
- operation: 'CREATE UI Builder Data Broker',
2331
- sys_id: sys_id,
2332
- name: args.name,
2333
- type: args.type || 'table',
2334
- verified_in_table: 'sys_ux_data_broker',
2335
- verification_timestamp: new Date().toISOString()
2336
- }
2091
+ data_broker: response.data,
2092
+ message: `Data broker '${args.name}' created for ${args.type} type`
2337
2093
  };
2338
2094
  }
2339
2095
  catch (error) {
@@ -2366,32 +2122,11 @@ ${configList}${layoutsText}${offlineText}
2366
2122
  if (!response.success) {
2367
2123
  throw new Error(`Failed to configure data broker: ${response.error}`);
2368
2124
  }
2369
- // VERIFICATION: Confirm data broker configuration was updated
2370
- const verification = await this.client.getRecord('sys_ux_data_broker', args.broker_id);
2371
- if (!verification.success) {
2372
- return {
2373
- success: false,
2374
- error: 'Data broker configuration reported success but record not found in sys_ux_data_broker table',
2375
- suggestion: 'Data broker may not exist or you may lack permissions to access it',
2376
- broker_id: args.broker_id,
2377
- verification_failed: true
2378
- };
2379
- }
2380
- this.logger.info(`✅ UI Builder data broker configured and verified: ${args.broker_id}`);
2125
+ this.logger.info('✅ UI Builder data broker configured successfully');
2381
2126
  return {
2382
2127
  success: true,
2383
- verified: true,
2384
- data_broker_sys_id: args.broker_id,
2385
- updates_applied: Object.keys(updates),
2386
- configured_at: new Date().toISOString(),
2387
- message: `✅ Data broker configuration updated and verified successfully`,
2388
- detailed_confirmation: {
2389
- operation: 'CONFIGURE UI Builder Data Broker',
2390
- sys_id: args.broker_id,
2391
- updates_applied: updates,
2392
- verified_in_table: 'sys_ux_data_broker',
2393
- verification_timestamp: new Date().toISOString()
2394
- }
2128
+ data_broker: response.data,
2129
+ message: 'Data broker configuration updated successfully'
2395
2130
  };
2396
2131
  }
2397
2132
  catch (error) {
@@ -2612,48 +2347,11 @@ ${configList}${layoutsText}${offlineText}
2612
2347
  if (!response.success) {
2613
2348
  throw new Error(`Failed to create client script: ${response.error}`);
2614
2349
  }
2615
- // VERIFICATION: Confirm client script was created (fix sys_id access)
2616
- const sys_id = response.data?.result?.sys_id || response.data?.sys_id;
2617
- if (!sys_id) {
2618
- return {
2619
- success: false,
2620
- error: 'Client script creation succeeded but no sys_id returned in response',
2621
- debug_info: {
2622
- has_data: !!response.data,
2623
- has_result: !!(response.data && response.data.result),
2624
- response_structure: typeof response.data
2625
- },
2626
- suggestion: 'ServiceNow API response format may be different than expected'
2627
- };
2628
- }
2629
- const verification = await this.client.getRecord('sys_ux_client_script', sys_id);
2630
- if (!verification.success) {
2631
- return {
2632
- success: false,
2633
- error: 'Client script creation reported success but record not found in sys_ux_client_script table',
2634
- suggestion: 'Client script creation may have been rolled back due to script validation errors',
2635
- verification_failed: true
2636
- };
2637
- }
2638
- this.logger.info(`✅ UI Builder client script created and verified: ${sys_id}`);
2350
+ this.logger.info('✅ UI Builder client script created successfully');
2639
2351
  return {
2640
2352
  success: true,
2641
- verified: true,
2642
- client_script_sys_id: sys_id,
2643
- script_name: args.name,
2644
- script_type: args.type,
2645
- page_id: args.page_id,
2646
- created_at: new Date().toISOString(),
2647
- message: `✅ Client script '${args.name}' created and verified successfully`,
2648
- detailed_confirmation: {
2649
- operation: 'CREATE UI Builder Client Script',
2650
- sys_id: sys_id,
2651
- name: args.name,
2652
- type: args.type,
2653
- page_reference: args.page_id,
2654
- verified_in_table: 'sys_ux_client_script',
2655
- verification_timestamp: new Date().toISOString()
2656
- }
2353
+ script: response.data,
2354
+ message: `Client script '${args.name}' created for ${args.type} trigger`
2657
2355
  };
2658
2356
  }
2659
2357
  catch (error) {
@@ -2715,49 +2413,11 @@ ${configList}${layoutsText}${offlineText}
2715
2413
  if (!response.success) {
2716
2414
  throw new Error(`Failed to create event: ${response.error}`);
2717
2415
  }
2718
- // VERIFICATION: Confirm event was created (fix sys_id access)
2719
- const sys_id = response.data?.result?.sys_id || response.data?.sys_id;
2720
- if (!sys_id) {
2721
- return {
2722
- success: false,
2723
- error: 'Event creation succeeded but no sys_id returned in response',
2724
- debug_info: {
2725
- has_data: !!response.data,
2726
- has_result: !!(response.data && response.data.result),
2727
- response_structure: typeof response.data
2728
- },
2729
- suggestion: 'ServiceNow API response format may be different than expected'
2730
- };
2731
- }
2732
- const verification = await this.client.getRecord('sys_ux_event', sys_id);
2733
- if (!verification.success) {
2734
- return {
2735
- success: false,
2736
- error: 'Event creation reported success but record not found in sys_ux_event table',
2737
- suggestion: 'Event creation may have been rolled back due to validation errors',
2738
- verification_failed: true
2739
- };
2740
- }
2741
- this.logger.info(`✅ UI Builder event created and verified: ${sys_id}`);
2416
+ this.logger.info('✅ UI Builder event created successfully');
2742
2417
  return {
2743
2418
  success: true,
2744
- verified: true,
2745
- event_sys_id: sys_id,
2746
- event_name: args.name,
2747
- event_scope: args.global_event ? 'Global' : 'Component Scoped',
2748
- component_scope: args.component_scope || 'Not specified',
2749
- created_at: new Date().toISOString(),
2750
- message: `✅ Custom event '${args.name}' created and verified successfully`,
2751
- detailed_confirmation: {
2752
- operation: 'CREATE UI Builder Event',
2753
- sys_id: sys_id,
2754
- name: args.name,
2755
- global_event: args.global_event || false,
2756
- bubbles: args.bubbles !== false,
2757
- cancelable: args.cancelable !== false,
2758
- verified_in_table: 'sys_ux_event',
2759
- verification_timestamp: new Date().toISOString()
2760
- }
2419
+ event: response.data,
2420
+ message: `Custom event '${args.name}' created ${args.global_event ? '(global)' : '(scoped)'}`
2761
2421
  };
2762
2422
  }
2763
2423
  catch (error) {
@@ -3037,55 +2697,18 @@ ${configList}${layoutsText}${offlineText}
3037
2697
  };
3038
2698
  }
3039
2699
  const result = await this.client.createRecord('sys_ux_experience', experienceData);
3040
- // ENHANCED FEEDBACK SYSTEM
3041
2700
  if (result.success && result.data && result.data.result && result.data.result.sys_id) {
3042
- const sys_id = result.data.result.sys_id;
3043
- // VERIFICATION: Confirm record actually exists
3044
- const verification = await this.client.getRecord('sys_ux_experience', sys_id);
3045
- if (!verification.success) {
3046
- return {
3047
- success: false,
3048
- error: `UX Experience creation reported success but record not found in sys_ux_experience table`,
3049
- suggestion: 'Record creation may have failed silently or been rolled back due to permissions',
3050
- reported_sys_id: sys_id,
3051
- verification_failed: true
3052
- };
3053
- }
3054
- this.logger.info(`✅ UX Experience created and verified with sys_id: ${sys_id}`);
2701
+ this.logger.info(`✅ UX Experience created with sys_id: ${result.data.result.sys_id}`);
3055
2702
  return {
3056
2703
  success: true,
3057
- verified: true,
3058
- experience_sys_id: sys_id,
3059
- experience_name: args.name,
3060
- shell_macroponent: shellSysId ? 'Linked to app shell' : 'No shell linked',
3061
- created_at: new Date().toISOString(),
3062
- table: 'sys_ux_experience',
3063
- message: `✅ UX Experience '${args.name}' created and verified successfully`,
3064
- detailed_confirmation: {
3065
- operation: 'CREATE UX Experience',
3066
- sys_id: sys_id,
3067
- name: args.name,
3068
- active: true,
3069
- verified_in_table: 'sys_ux_experience',
3070
- verification_timestamp: new Date().toISOString()
3071
- },
3072
- next_step: `Create App Configuration using experience_sys_id: ${sys_id}`
2704
+ experience_sys_id: result.data.result.sys_id,
2705
+ message: `Experience '${args.name}' created successfully`,
2706
+ next_step: "Create App Configuration using this experience_sys_id"
3073
2707
  };
3074
2708
  }
3075
2709
  else {
3076
2710
  const error = (result.data && result.data.error) || (result.error) || 'Unknown error creating experience';
3077
- return {
3078
- success: false,
3079
- error: `Failed to create UX Experience: ${error}`,
3080
- suggestion: this.getErrorSuggestion(error),
3081
- operation_attempted: 'CREATE sys_ux_experience',
3082
- debug_info: {
3083
- result_success: result.success,
3084
- has_data: !!(result.data),
3085
- has_result: !!(result.data && result.data.result),
3086
- has_sys_id: !!(result.data && result.data.result && result.data.result.sys_id)
3087
- }
3088
- };
2711
+ throw new Error(`Failed to create experience: ${error}`);
3089
2712
  }
3090
2713
  }
3091
2714
  catch (error) {
@@ -3127,43 +2750,17 @@ ${configList}${layoutsText}${offlineText}
3127
2750
  };
3128
2751
  const result = await this.client.createRecord('sys_ux_app_config', configData);
3129
2752
  if (result.success && result.data && result.data.result && result.data.result.sys_id) {
3130
- const sys_id = result.data.result.sys_id;
3131
- // VERIFICATION: Confirm app config was created
3132
- const verification = await this.client.getRecord('sys_ux_app_config', sys_id);
3133
- if (!verification.success) {
3134
- return {
3135
- success: false,
3136
- error: 'App config creation reported success but record not found in sys_ux_app_config table',
3137
- verification_failed: true
3138
- };
3139
- }
3140
- this.logger.info(`✅ UX App Config created and verified: ${sys_id}`);
2753
+ this.logger.info(`✅ UX App Config created with sys_id: ${result.data.result.sys_id}`);
3141
2754
  return {
3142
2755
  success: true,
3143
- verified: true,
3144
- app_config_sys_id: sys_id,
3145
- config_name: args.name,
3146
- linked_experience: args.experience_sys_id,
3147
- created_at: new Date().toISOString(),
3148
- message: `✅ App Configuration '${args.name}' created and verified successfully`,
3149
- detailed_confirmation: {
3150
- operation: 'CREATE UX App Config',
3151
- sys_id: sys_id,
3152
- name: args.name,
3153
- experience_assoc: args.experience_sys_id,
3154
- verified_in_table: 'sys_ux_app_config',
3155
- verification_timestamp: new Date().toISOString()
3156
- },
3157
- next_step: `Create Page Macroponent using app_config_sys_id: ${sys_id}`
2756
+ app_config_sys_id: result.data.result.sys_id,
2757
+ message: `App Configuration '${args.name}' created successfully`,
2758
+ next_step: "Create Page Macroponent using this app_config_sys_id"
3158
2759
  };
3159
2760
  }
3160
2761
  else {
3161
2762
  const error = (result.data && result.data.error) || (result.error) || 'Unknown error creating app config';
3162
- return {
3163
- success: false,
3164
- error: `Failed to create app config: ${error}`,
3165
- suggestion: this.getErrorSuggestion(error)
3166
- };
2763
+ throw new Error(`Failed to create app config: ${error}`);
3167
2764
  }
3168
2765
  }
3169
2766
  catch (error) {
@@ -3719,226 +3316,6 @@ ${configList}${layoutsText}${offlineText}
3719
3316
  throw error;
3720
3317
  }
3721
3318
  }
3722
- /**
3723
- * COMPREHENSIVE TOOL HEALTH TESTING
3724
- * Tests all workspace tools and provides detailed status report
3725
- */
3726
- async testAllWorkspaceTools(args) {
3727
- try {
3728
- this.logger.info('🛠️ Starting comprehensive tool health test...');
3729
- const testResults = {
3730
- test_timestamp: new Date().toISOString(),
3731
- tools_tested: 0,
3732
- tools_working: 0,
3733
- tools_failing: 0,
3734
- tools_unclear: 0,
3735
- detailed_results: [],
3736
- plugin_status: {},
3737
- recommendations: []
3738
- };
3739
- // Test critical plugins first
3740
- const pluginTests = [
3741
- { name: 'UI Builder', table: 'sys_ux_page', description: 'UI Builder functionality' },
3742
- { name: 'Now Experience Framework', table: 'sys_ux_experience', description: 'UX Workspace creation' },
3743
- { name: 'Agent Workspace', table: 'sys_ux_app_route', description: 'Configurable Agent Workspaces' },
3744
- { name: 'Mobile Publishing', table: 'sys_push_notif_msg', description: 'Mobile app management' },
3745
- { name: 'Flow Designer', table: 'sys_hub_flow', description: 'Flow automation' }
3746
- ];
3747
- for (const plugin of pluginTests) {
3748
- const pluginTest = await this.client.searchRecords(plugin.table, '', 1);
3749
- testResults.plugin_status[plugin.name] = {
3750
- available: pluginTest.success,
3751
- table: plugin.table,
3752
- description: plugin.description,
3753
- status: pluginTest.success ? '✅ Available' : '❌ Not Available'
3754
- };
3755
- }
3756
- // Test individual tools
3757
- const toolTests = [
3758
- // UX Experience tools
3759
- {
3760
- name: 'snow_create_ux_experience',
3761
- test: () => this.snow_create_ux_experience({ name: 'Health Test Experience' }),
3762
- category: 'UX Experience',
3763
- expects_sys_id: true
3764
- },
3765
- // UI Builder tools
3766
- {
3767
- name: 'snow_discover_uib_pages',
3768
- test: () => this.discoverUIBuilderPages({}),
3769
- category: 'UI Builder',
3770
- expects_sys_id: false
3771
- },
3772
- // Mobile tools
3773
- {
3774
- name: 'snow_configure_mobile_app',
3775
- test: () => this.configureMobileApp({ app_name: 'Health Test App' }),
3776
- category: 'Mobile',
3777
- expects_sys_id: true
3778
- }
3779
- ];
3780
- for (const toolTest of toolTests) {
3781
- try {
3782
- testResults.tools_tested++;
3783
- const testStart = Date.now();
3784
- const result = await toolTest.test();
3785
- const testDuration = Date.now() - testStart;
3786
- let status = '❌ FAILED';
3787
- let feedback = 'No response';
3788
- if (result && result.success === true) {
3789
- if (toolTest.expects_sys_id && result.sys_id) {
3790
- status = '✅ WORKING';
3791
- feedback = `Created record with sys_id: ${result.sys_id}`;
3792
- testResults.tools_working++;
3793
- }
3794
- else if (!toolTest.expects_sys_id) {
3795
- status = '✅ WORKING';
3796
- feedback = 'Operation completed successfully';
3797
- testResults.tools_working++;
3798
- }
3799
- else {
3800
- status = '⚠️ UNCLEAR';
3801
- feedback = 'Success reported but no sys_id returned';
3802
- testResults.tools_unclear++;
3803
- }
3804
- }
3805
- else if (result && result.success === false) {
3806
- status = '❌ FAILED';
3807
- feedback = result.error || 'Unknown error';
3808
- testResults.tools_failing++;
3809
- }
3810
- else {
3811
- status = '⚠️ UNCLEAR';
3812
- feedback = 'No clear success/failure indication';
3813
- testResults.tools_unclear++;
3814
- }
3815
- testResults.detailed_results.push({
3816
- tool: toolTest.name,
3817
- category: toolTest.category,
3818
- status: status,
3819
- feedback: feedback,
3820
- execution_time_ms: testDuration,
3821
- expects_sys_id: toolTest.expects_sys_id,
3822
- actual_result: result
3823
- });
3824
- }
3825
- catch (error) {
3826
- testResults.tools_tested++;
3827
- testResults.tools_failing++;
3828
- testResults.detailed_results.push({
3829
- tool: toolTest.name,
3830
- category: toolTest.category,
3831
- status: '❌ FAILED',
3832
- feedback: `Exception: ${error}`,
3833
- execution_time_ms: 0,
3834
- error_type: 'EXCEPTION'
3835
- });
3836
- }
3837
- }
3838
- // Generate recommendations
3839
- if (testResults.tools_working === 0) {
3840
- testResults.recommendations.push('No tools are working - check authentication and instance setup');
3841
- }
3842
- if (testResults.tools_unclear > 0) {
3843
- testResults.recommendations.push('Some tools have unclear status - implement better response validation');
3844
- }
3845
- this.logger.info(`✅ Tool health test completed: ${testResults.tools_working}/${testResults.tools_tested} working`);
3846
- return {
3847
- success: true,
3848
- test_summary: testResults,
3849
- message: `Tool health test completed: ${testResults.tools_working}/${testResults.tools_tested} tools working properly`,
3850
- detailed_report: testResults.detailed_results
3851
- };
3852
- }
3853
- catch (error) {
3854
- this.logger.error('Failed to test workspace tools:', error);
3855
- return {
3856
- success: false,
3857
- error: `Failed to test workspace tools: ${error}`,
3858
- suggestion: 'Check ServiceNow connectivity and authentication',
3859
- operation_attempted: 'TEST All Workspace Tools'
3860
- };
3861
- }
3862
- }
3863
- /**
3864
- * CHECK PLUGIN AVAILABILITY
3865
- * Comprehensive plugin and licensing status check
3866
- */
3867
- async checkPluginAvailability(args) {
3868
- try {
3869
- this.logger.info('🔌 Checking ServiceNow plugin availability...');
3870
- const pluginChecks = [];
3871
- if (args.check_ui_builder) {
3872
- const uiBuilderCheck = await this.client.searchRecords('sys_ux_page', '', 1);
3873
- pluginChecks.push({
3874
- name: 'UI Builder',
3875
- table: 'sys_ux_page',
3876
- available: uiBuilderCheck.success,
3877
- error: uiBuilderCheck.success ? null : uiBuilderCheck.error,
3878
- status: uiBuilderCheck.success ? '✅ Available' : '❌ Not Available',
3879
- recommendation: uiBuilderCheck.success ? 'UI Builder tools should work' : 'Install UI Builder plugin from ServiceNow Store'
3880
- });
3881
- }
3882
- if (args.check_uxf) {
3883
- const uxfCheck = await this.client.searchRecords('sys_ux_experience', '', 1);
3884
- pluginChecks.push({
3885
- name: 'Now Experience Framework',
3886
- table: 'sys_ux_experience',
3887
- available: uxfCheck.success,
3888
- error: uxfCheck.success ? null : uxfCheck.error,
3889
- status: uxfCheck.success ? '✅ Available' : '❌ Not Available',
3890
- recommendation: uxfCheck.success ? 'UX workspace creation should work' : 'Enable Now Experience Framework in instance'
3891
- });
3892
- }
3893
- if (args.check_agent_workspace) {
3894
- const agentCheck = await this.client.searchRecords('sys_ux_screen_type', '', 1);
3895
- pluginChecks.push({
3896
- name: 'Agent Workspace',
3897
- table: 'sys_ux_screen_type',
3898
- available: agentCheck.success,
3899
- error: agentCheck.success ? null : agentCheck.error,
3900
- status: agentCheck.success ? '✅ Available' : '❌ Not Available',
3901
- recommendation: agentCheck.success ? 'Agent workspace tools should work' : 'Install Agent Workspace plugin'
3902
- });
3903
- }
3904
- if (args.check_mobile) {
3905
- const mobileCheck = await this.client.searchRecords('sys_push_notif_msg', '', 1);
3906
- pluginChecks.push({
3907
- name: 'Mobile Publishing',
3908
- table: 'sys_push_notif_msg',
3909
- available: mobileCheck.success,
3910
- error: mobileCheck.success ? null : mobileCheck.error,
3911
- status: mobileCheck.success ? '✅ Available' : '❌ Not Available',
3912
- recommendation: mobileCheck.success ? 'Mobile tools should work' : 'Install Mobile Publishing plugin (requires additional licensing)'
3913
- });
3914
- }
3915
- const availableCount = pluginChecks.filter(p => p.available).length;
3916
- const totalCount = pluginChecks.length;
3917
- this.logger.info(`✅ Plugin check completed: ${availableCount}/${totalCount} plugins available`);
3918
- return {
3919
- success: true,
3920
- plugin_summary: {
3921
- total_checked: totalCount,
3922
- available: availableCount,
3923
- unavailable: totalCount - availableCount,
3924
- percentage: Math.round((availableCount / totalCount) * 100)
3925
- },
3926
- plugins: pluginChecks,
3927
- message: `Plugin availability check: ${availableCount}/${totalCount} plugins available`,
3928
- overall_status: availableCount === totalCount ? 'All plugins available' :
3929
- availableCount > 0 ? 'Partial plugin availability' : 'No plugins available'
3930
- };
3931
- }
3932
- catch (error) {
3933
- this.logger.error('Failed to check plugin availability:', error);
3934
- return {
3935
- success: false,
3936
- error: `Failed to check plugin availability: ${error}`,
3937
- suggestion: 'Check ServiceNow connectivity and basic table access permissions',
3938
- operation_attempted: 'CHECK Plugin Availability'
3939
- };
3940
- }
3941
- }
3942
3319
  /**
3943
3320
  * CONFIGURABLE AGENT WORKSPACE: Create using UX App architecture
3944
3321
  */
@@ -4045,144 +3422,6 @@ ${configList}${layoutsText}${offlineText}
4045
3422
  .replace(/^-|-$/g, '') // Trim leading/trailing hyphens
4046
3423
  .substring(0, 80); // Max 80 chars (ServiceNow field limit)
4047
3424
  }
4048
- /**
4049
- * ENHANCED RESPONSE VALIDATION SYSTEM
4050
- * Provides comprehensive feedback for all tool operations
4051
- */
4052
- async validateAndConfirmOperation(operationType, result, details) {
4053
- try {
4054
- // Standard validation for ServiceNow API responses
4055
- if (!result || typeof result !== 'object') {
4056
- return {
4057
- success: false,
4058
- error: `No response received from ServiceNow API for ${operationType}`,
4059
- suggestion: 'Check ServiceNow instance connectivity and authentication',
4060
- validation_result: 'NO_RESPONSE'
4061
- };
4062
- }
4063
- // Check for API success/failure
4064
- if (result.success === false) {
4065
- return {
4066
- success: false,
4067
- error: result.error || `${operationType} operation failed`,
4068
- suggestion: this.getErrorSuggestion(result.error || ''),
4069
- validation_result: 'API_FAILURE'
4070
- };
4071
- }
4072
- // Validate response data structure
4073
- if (result.success && (!result.data || !result.data.result)) {
4074
- return {
4075
- success: false,
4076
- error: `${operationType} succeeded but returned invalid data structure`,
4077
- suggestion: 'Check ServiceNow table permissions and field access',
4078
- validation_result: 'INVALID_DATA_STRUCTURE'
4079
- };
4080
- }
4081
- // Extract sys_id for verification
4082
- const sys_id = result.data?.result?.sys_id;
4083
- if (result.success && !sys_id) {
4084
- return {
4085
- success: false,
4086
- error: `${operationType} succeeded but no sys_id returned`,
4087
- suggestion: 'Record may have been created but sys_id is not accessible',
4088
- validation_result: 'MISSING_SYS_ID'
4089
- };
4090
- }
4091
- // VERIFICATION STEP: Confirm record actually exists
4092
- if (sys_id && details.table) {
4093
- const verification = await this.client.getRecord(details.table, sys_id);
4094
- if (!verification.success) {
4095
- return {
4096
- success: false,
4097
- error: `${operationType} reported success but record not found in ${details.table}`,
4098
- suggestion: 'Record creation may have failed silently or been rolled back',
4099
- validation_result: 'RECORD_NOT_FOUND',
4100
- reported_sys_id: sys_id
4101
- };
4102
- }
4103
- // SUCCESS with verification!
4104
- return {
4105
- success: true,
4106
- sys_id: sys_id,
4107
- verified: true,
4108
- operation_type: operationType,
4109
- table: details.table,
4110
- message: `${operationType} completed successfully`,
4111
- confirmation: `Record verified in ${details.table} with sys_id: ${sys_id}`,
4112
- validation_result: 'VERIFIED_SUCCESS'
4113
- };
4114
- }
4115
- // Success without verification (no sys_id or table)
4116
- return {
4117
- success: true,
4118
- operation_type: operationType,
4119
- message: `${operationType} completed`,
4120
- validation_result: 'SUCCESS_NO_VERIFICATION'
4121
- };
4122
- }
4123
- catch (error) {
4124
- this.logger.error('Validation error:', error);
4125
- return {
4126
- success: false,
4127
- error: `Validation failed for ${operationType}: ${error}`,
4128
- suggestion: 'Check ServiceNow connectivity and permissions',
4129
- validation_result: 'VALIDATION_ERROR'
4130
- };
4131
- }
4132
- }
4133
- /**
4134
- * Get actionable suggestions based on error type with specific tool guidance
4135
- */
4136
- getErrorSuggestion(error) {
4137
- const errorLower = error.toLowerCase();
4138
- if (errorLower.includes('403') || errorLower.includes('forbidden')) {
4139
- return 'PERMISSIONS ISSUE: You need specific roles. For UI Builder: ui_builder_admin + ui_builder_user. For Workspaces: workspace_admin. For Mobile: mobile_admin. Contact your ServiceNow admin.';
4140
- }
4141
- if (errorLower.includes('404') || errorLower.includes('not found')) {
4142
- return 'PLUGIN/TABLE MISSING: Required ServiceNow plugin not installed. UI Builder requires "UI Builder" plugin. Workspaces require "Agent Workspace" or "Now Experience Framework". Check ServiceNow Store.';
4143
- }
4144
- if (errorLower.includes('400') || errorLower.includes('bad request')) {
4145
- return 'INVALID DATA: Check required fields and data formats. Some tools need valid sys_ids from previous steps in the workflow.';
4146
- }
4147
- if (errorLower.includes('401') || errorLower.includes('unauthorized')) {
4148
- return 'AUTHENTICATION EXPIRED: Run "snow-flow auth login" to re-authenticate with ServiceNow.';
4149
- }
4150
- if (errorLower.includes('sys_id')) {
4151
- return 'SYS_ID ERROR: Invalid or missing sys_id in API response. This usually means the record creation failed silently.';
4152
- }
4153
- if (errorLower.includes('plugin') || errorLower.includes('license')) {
4154
- return 'LICENSING ISSUE: Required ServiceNow plugin/license not available. Contact ServiceNow admin for proper licensing.';
4155
- }
4156
- return 'UNKNOWN ERROR: Check ServiceNow system logs (System Logs > System Log > All) for detailed error information.';
4157
- }
4158
- /**
4159
- * Enhanced tool execution wrapper with comprehensive feedback
4160
- */
4161
- async executeWithFeedback(operationType, operation, details) {
4162
- try {
4163
- this.logger.info(`🔄 Executing ${operationType}...`);
4164
- const startTime = Date.now();
4165
- const result = await operation();
4166
- const executionTime = Date.now() - startTime;
4167
- const validation = await this.validateAndConfirmOperation(operationType, result, details);
4168
- return {
4169
- ...validation,
4170
- execution_time_ms: executionTime,
4171
- timestamp: new Date().toISOString()
4172
- };
4173
- }
4174
- catch (error) {
4175
- this.logger.error(`❌ ${operationType} failed:`, error);
4176
- return {
4177
- success: false,
4178
- operation_type: operationType,
4179
- error: error instanceof Error ? error.message : String(error),
4180
- suggestion: this.getErrorSuggestion(String(error)),
4181
- validation_result: 'EXECUTION_ERROR',
4182
- timestamp: new Date().toISOString()
4183
- };
4184
- }
4185
- }
4186
3425
  /**
4187
3426
  * Validate workspace configuration (fix from user feedback)
4188
3427
  */
@@ -4202,9 +3441,32 @@ ${configList}${layoutsText}${offlineText}
4202
3441
  return errors;
4203
3442
  }
4204
3443
  async run() {
4205
- const transport = new stdio_js_1.StdioServerTransport();
4206
- await this.server.connect(transport);
4207
- this.logger.info('ServiceNow Flow/Workspace/Mobile MCP Server running on stdio');
3444
+ try {
3445
+ const transport = new stdio_js_1.StdioServerTransport();
3446
+ // Simple timeout protection (prevents hanging)
3447
+ const connectTimeout = setTimeout(() => {
3448
+ this.logger.error('❌ MCP connection timeout after 30 seconds');
3449
+ process.exit(1);
3450
+ }, 30000);
3451
+ await this.server.connect(transport);
3452
+ clearTimeout(connectTimeout);
3453
+ this.logger.info('✅ ServiceNow Flow/Workspace/Mobile MCP Server running on stdio');
3454
+ // Simple keep-alive (prevents disconnects)
3455
+ setInterval(() => {
3456
+ this.logger.debug('💚 MCP server alive - uptime: ' + Math.round((Date.now() - Date.now()) / 60000) + 'min');
3457
+ }, 120000); // Every 2 minutes
3458
+ }
3459
+ catch (error) {
3460
+ this.logger.error('❌ MCP server failed to start:', error);
3461
+ // Simple retry once
3462
+ this.logger.info('🔄 Retrying MCP connection once...');
3463
+ setTimeout(() => {
3464
+ this.run().catch(() => {
3465
+ this.logger.error('💥 MCP retry failed - exiting');
3466
+ process.exit(1);
3467
+ });
3468
+ }, 3000);
3469
+ }
4208
3470
  }
4209
3471
  }
4210
3472
  const server = new ServiceNowFlowWorkspaceMobileMCP();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "4.5.51",
3
+ "version": "4.5.53",
4
4
  "description": "Conversational ServiceNow development platform using Claude Code. Multi-agent orchestration with 20+ MCP servers providing 245+ ServiceNow tools including complete UX + Agent Workspace creation with official APIs.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",