snow-flow 4.5.50 → 4.5.52

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.
@@ -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,40 +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
1416
- const sys_id = response.data.result.sys_id;
1417
- const verification = await this.client.getRecord('sys_mobile_application_config', sys_id);
1418
- if (!verification.success) {
1419
- return {
1420
- success: false,
1421
- error: 'Mobile app configuration reported success but record not found in sys_mobile_application_config table',
1422
- suggestion: 'Mobile app configuration may have been rolled back due to validation errors',
1423
- verification_failed: true
1424
- };
1425
- }
1426
- this.logger.info(`✅ Mobile app configured and verified: ${sys_id}`);
1427
1404
  return {
1428
- success: true,
1429
- verified: true,
1430
- mobile_app_sys_id: sys_id,
1431
- app_name: args.app_name,
1432
- authentication: args.authentication || 'oauth',
1433
- modules_count: args.enabled_modules ? args.enabled_modules.length : 0,
1434
- offline_tables_count: args.offline_tables ? args.offline_tables.length : 0,
1435
- push_enabled: args.push_enabled !== false,
1436
- created_at: new Date().toISOString(),
1437
- message: `✅ Mobile app '${args.app_name}' configured and verified successfully`,
1438
- detailed_confirmation: {
1439
- operation: 'CONFIGURE Mobile App',
1440
- sys_id: sys_id,
1441
- app_name: args.app_name,
1442
- authentication_method: args.authentication || 'oauth',
1443
- enabled_modules: args.enabled_modules || [],
1444
- offline_tables: args.offline_tables || [],
1445
- push_notifications: args.push_enabled !== false,
1446
- verified_in_table: 'sys_mobile_application_config',
1447
- verification_timestamp: new Date().toISOString()
1448
- }
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
+ }]
1449
1418
  };
1450
1419
  }
1451
1420
  catch (error) {
@@ -1478,39 +1447,20 @@ ${executionList}
1478
1447
  if (!response.success) {
1479
1448
  throw new Error(`Failed to create mobile layout: ${response.error}`);
1480
1449
  }
1481
- // VERIFICATION: Confirm mobile layout was created
1482
- const sys_id = response.data.result.sys_id;
1483
- const verification = await this.client.getRecord('sys_mobile_layout', sys_id);
1484
- if (!verification.success) {
1485
- return {
1486
- success: false,
1487
- error: 'Mobile layout creation reported success but record not found in sys_mobile_layout table',
1488
- suggestion: 'Mobile layout creation may have been rolled back due to validation errors',
1489
- verification_failed: true
1490
- };
1491
- }
1492
- this.logger.info(`✅ Mobile layout created and verified: ${sys_id}`);
1493
1450
  return {
1494
- success: true,
1495
- verified: true,
1496
- mobile_layout_sys_id: sys_id,
1497
- layout_name: args.name,
1498
- layout_table: args.table,
1499
- layout_type: args.type,
1500
- fields_count: args.fields ? args.fields.length : 0,
1501
- related_lists_count: args.related_lists ? args.related_lists.length : 0,
1502
- created_at: new Date().toISOString(),
1503
- message: `✅ Mobile layout '${args.name}' created and verified successfully`,
1504
- detailed_confirmation: {
1505
- operation: 'CREATE Mobile Layout',
1506
- sys_id: sys_id,
1507
- name: args.name,
1508
- table: args.table,
1509
- type: args.type,
1510
- fields: args.fields || [],
1511
- verified_in_table: 'sys_mobile_layout',
1512
- verification_timestamp: new Date().toISOString()
1513
- }
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
+ }]
1514
1464
  };
1515
1465
  }
1516
1466
  catch (error) {
@@ -1876,30 +1826,9 @@ ${configList}${layoutsText}${offlineText}
1876
1826
  const query = conditions.join('^');
1877
1827
  const pagesResponse = await this.client.searchRecords('sys_ux_page', query, args.limit || 50);
1878
1828
  if (!pagesResponse.success) {
1879
- return {
1880
- success: false,
1881
- error: `Failed to discover UI Builder pages: ${pagesResponse.error}`,
1882
- suggestion: 'UI Builder plugin may not be installed. Check ServiceNow Store for UI Builder plugin.',
1883
- plugin_required: 'UI Builder',
1884
- table_tested: 'sys_ux_page'
1885
- };
1886
- }
1887
- const pages = pagesResponse.data.result || [];
1888
- // Handle no results case
1889
- if (pages.length === 0) {
1890
- return {
1891
- success: true,
1892
- pages: [],
1893
- count: 0,
1894
- message: '📝 No UI Builder pages found',
1895
- explanation: 'This could mean: 1) No pages exist yet, 2) UI Builder plugin not installed, 3) Insufficient permissions to view pages',
1896
- suggestions: [
1897
- 'Create your first UI Builder page using snow_create_uib_page',
1898
- 'Check if UI Builder plugin is installed and activated',
1899
- 'Verify you have ui_builder_user or ui_builder_admin roles'
1900
- ]
1901
- };
1829
+ throw new Error(`Failed to discover UI Builder pages: ${pagesResponse.error}`);
1902
1830
  }
1831
+ const pages = pagesResponse.data.result;
1903
1832
  // Enrich with additional data if requested
1904
1833
  for (const page of pages) {
1905
1834
  if (args.include_routing) {
@@ -1918,18 +1847,8 @@ ${configList}${layoutsText}${offlineText}
1918
1847
  this.logger.info(`✅ Found ${pages.length} UI Builder pages`);
1919
1848
  return {
1920
1849
  success: true,
1921
- verified: true,
1922
1850
  pages: pages,
1923
- count: pages.length,
1924
- query_used: query || 'No filter',
1925
- message: `✅ Successfully discovered ${pages.length} UI Builder pages`,
1926
- detailed_confirmation: {
1927
- operation: 'DISCOVER UI Builder Pages',
1928
- table_searched: 'sys_ux_page',
1929
- results_count: pages.length,
1930
- query_conditions: conditions.join(', ') || 'No conditions',
1931
- search_timestamp: new Date().toISOString()
1932
- }
1851
+ count: pages.length
1933
1852
  };
1934
1853
  }
1935
1854
  catch (error) {
@@ -1975,34 +1894,12 @@ ${configList}${layoutsText}${offlineText}
1975
1894
  await this.client.deleteRecord('sys_ux_lib_source_script', sourceResponse.data.sys_id);
1976
1895
  throw new Error(`Failed to create component: ${componentResponse.error}`);
1977
1896
  }
1978
- // VERIFICATION: Confirm both records were created
1979
- const componentVerification = await this.client.getRecord('sys_ux_lib_component', componentResponse.data.result.sys_id);
1980
- const sourceVerification = await this.client.getRecord('sys_ux_lib_source_script', sourceResponse.data.result.sys_id);
1981
- if (!componentVerification.success || !sourceVerification.success) {
1982
- return {
1983
- success: false,
1984
- error: 'Component creation reported success but records not found in tables',
1985
- suggestion: 'Component creation may have been rolled back due to validation errors',
1986
- verification_failed: true
1987
- };
1988
- }
1989
- this.logger.info(`✅ UI Builder component created and verified: ${componentResponse.data.result.sys_id}`);
1897
+ this.logger.info('✅ UI Builder component created successfully');
1990
1898
  return {
1991
1899
  success: true,
1992
- verified: true,
1993
- component_sys_id: componentResponse.data.result.sys_id,
1994
- source_script_sys_id: sourceResponse.data.result.sys_id,
1995
- component_name: args.name,
1996
- category: args.category || 'custom',
1997
- created_at: new Date().toISOString(),
1998
- message: `✅ Custom UI Builder component '${args.name}' created and verified successfully`,
1999
- detailed_confirmation: {
2000
- operation: 'CREATE UI Builder Component',
2001
- component_sys_id: componentResponse.data.result.sys_id,
2002
- source_script_sys_id: sourceResponse.data.result.sys_id,
2003
- verified_in_tables: ['sys_ux_lib_component', 'sys_ux_lib_source_script'],
2004
- verification_timestamp: new Date().toISOString()
2005
- }
1900
+ component: componentResponse.data,
1901
+ source_script: sourceResponse.data,
1902
+ message: `Custom UI Builder component '${args.name}' created successfully`
2006
1903
  };
2007
1904
  }
2008
1905
  catch (error) {
@@ -2081,31 +1978,9 @@ ${configList}${layoutsText}${offlineText}
2081
1978
  const query = conditions.join('^');
2082
1979
  const componentsResponse = await this.client.searchRecords('sys_ux_lib_component', query, args.limit || 100);
2083
1980
  if (!componentsResponse.success) {
2084
- return {
2085
- success: false,
2086
- error: `Failed to discover UI Builder components: ${componentsResponse.error}`,
2087
- suggestion: 'UI Builder plugin may not be installed. Check ServiceNow Store for UI Builder plugin.',
2088
- plugin_required: 'UI Builder',
2089
- table_tested: 'sys_ux_lib_component'
2090
- };
2091
- }
2092
- const components = componentsResponse.data.result || [];
2093
- // Handle no results case
2094
- if (components.length === 0) {
2095
- return {
2096
- success: true,
2097
- components: [],
2098
- count: 0,
2099
- message: '📝 No UI Builder components found',
2100
- explanation: 'This could mean: 1) No custom components exist, 2) UI Builder plugin not installed, 3) Insufficient permissions',
2101
- query_used: query || 'No filter',
2102
- suggestions: [
2103
- 'Create your first custom component using snow_create_uib_component',
2104
- 'Check built-in components by removing custom_only filter',
2105
- 'Verify UI Builder plugin is installed and you have proper permissions'
2106
- ]
2107
- };
1981
+ throw new Error(`Failed to discover components: ${componentsResponse.error}`);
2108
1982
  }
1983
+ const components = componentsResponse.data.result;
2109
1984
  // Enrich with additional data if requested
2110
1985
  for (const component of components) {
2111
1986
  if (args.include_source && component.source_script) {
@@ -2123,24 +1998,8 @@ ${configList}${layoutsText}${offlineText}
2123
1998
  this.logger.info(`✅ Found ${components.length} UI Builder components`);
2124
1999
  return {
2125
2000
  success: true,
2126
- verified: true,
2127
2001
  components: components,
2128
- count: components.length,
2129
- query_used: query || 'No filter',
2130
- categories_found: [...new Set(components.map(c => c.category))],
2131
- message: `✅ Successfully discovered ${components.length} UI Builder components`,
2132
- detailed_confirmation: {
2133
- operation: 'DISCOVER UI Builder Components',
2134
- table_searched: 'sys_ux_lib_component',
2135
- results_count: components.length,
2136
- query_conditions: conditions.join(', ') || 'No conditions',
2137
- enrichment_options: {
2138
- source_included: !!args.include_source,
2139
- usage_stats_included: !!args.include_usage_stats,
2140
- dependencies_included: !!args.include_dependencies
2141
- },
2142
- search_timestamp: new Date().toISOString()
2143
- }
2002
+ count: components.length
2144
2003
  };
2145
2004
  }
2146
2005
  catch (error) {
@@ -2226,35 +2085,11 @@ ${configList}${layoutsText}${offlineText}
2226
2085
  if (!response.success) {
2227
2086
  throw new Error(`Failed to create data broker: ${response.error}`);
2228
2087
  }
2229
- // VERIFICATION: Confirm data broker was created
2230
- const sys_id = response.data.result.sys_id;
2231
- const verification = await this.client.getRecord('sys_ux_data_broker', sys_id);
2232
- if (!verification.success) {
2233
- return {
2234
- success: false,
2235
- error: 'Data broker creation reported success but record not found in sys_ux_data_broker table',
2236
- suggestion: 'Data broker creation may have been rolled back due to validation errors',
2237
- verification_failed: true
2238
- };
2239
- }
2240
- this.logger.info(`✅ UI Builder data broker created and verified: ${sys_id}`);
2088
+ this.logger.info('✅ UI Builder data broker created successfully');
2241
2089
  return {
2242
2090
  success: true,
2243
- verified: true,
2244
- data_broker_sys_id: sys_id,
2245
- broker_name: args.name,
2246
- broker_type: args.type || 'table',
2247
- target_table: args.table || 'N/A',
2248
- created_at: new Date().toISOString(),
2249
- message: `✅ Data broker '${args.name}' created and verified successfully`,
2250
- detailed_confirmation: {
2251
- operation: 'CREATE UI Builder Data Broker',
2252
- sys_id: sys_id,
2253
- name: args.name,
2254
- type: args.type || 'table',
2255
- verified_in_table: 'sys_ux_data_broker',
2256
- verification_timestamp: new Date().toISOString()
2257
- }
2091
+ data_broker: response.data,
2092
+ message: `Data broker '${args.name}' created for ${args.type} type`
2258
2093
  };
2259
2094
  }
2260
2095
  catch (error) {
@@ -2287,32 +2122,11 @@ ${configList}${layoutsText}${offlineText}
2287
2122
  if (!response.success) {
2288
2123
  throw new Error(`Failed to configure data broker: ${response.error}`);
2289
2124
  }
2290
- // VERIFICATION: Confirm data broker configuration was updated
2291
- const verification = await this.client.getRecord('sys_ux_data_broker', args.broker_id);
2292
- if (!verification.success) {
2293
- return {
2294
- success: false,
2295
- error: 'Data broker configuration reported success but record not found in sys_ux_data_broker table',
2296
- suggestion: 'Data broker may not exist or you may lack permissions to access it',
2297
- broker_id: args.broker_id,
2298
- verification_failed: true
2299
- };
2300
- }
2301
- this.logger.info(`✅ UI Builder data broker configured and verified: ${args.broker_id}`);
2125
+ this.logger.info('✅ UI Builder data broker configured successfully');
2302
2126
  return {
2303
2127
  success: true,
2304
- verified: true,
2305
- data_broker_sys_id: args.broker_id,
2306
- updates_applied: Object.keys(updates),
2307
- configured_at: new Date().toISOString(),
2308
- message: `✅ Data broker configuration updated and verified successfully`,
2309
- detailed_confirmation: {
2310
- operation: 'CONFIGURE UI Builder Data Broker',
2311
- sys_id: args.broker_id,
2312
- updates_applied: updates,
2313
- verified_in_table: 'sys_ux_data_broker',
2314
- verification_timestamp: new Date().toISOString()
2315
- }
2128
+ data_broker: response.data,
2129
+ message: 'Data broker configuration updated successfully'
2316
2130
  };
2317
2131
  }
2318
2132
  catch (error) {
@@ -2533,36 +2347,11 @@ ${configList}${layoutsText}${offlineText}
2533
2347
  if (!response.success) {
2534
2348
  throw new Error(`Failed to create client script: ${response.error}`);
2535
2349
  }
2536
- // VERIFICATION: Confirm client script was created
2537
- const sys_id = response.data.result.sys_id;
2538
- const verification = await this.client.getRecord('sys_ux_client_script', sys_id);
2539
- if (!verification.success) {
2540
- return {
2541
- success: false,
2542
- error: 'Client script creation reported success but record not found in sys_ux_client_script table',
2543
- suggestion: 'Client script creation may have been rolled back due to script validation errors',
2544
- verification_failed: true
2545
- };
2546
- }
2547
- this.logger.info(`✅ UI Builder client script created and verified: ${sys_id}`);
2350
+ this.logger.info('✅ UI Builder client script created successfully');
2548
2351
  return {
2549
2352
  success: true,
2550
- verified: true,
2551
- client_script_sys_id: sys_id,
2552
- script_name: args.name,
2553
- script_type: args.type,
2554
- page_id: args.page_id,
2555
- created_at: new Date().toISOString(),
2556
- message: `✅ Client script '${args.name}' created and verified successfully`,
2557
- detailed_confirmation: {
2558
- operation: 'CREATE UI Builder Client Script',
2559
- sys_id: sys_id,
2560
- name: args.name,
2561
- type: args.type,
2562
- page_reference: args.page_id,
2563
- verified_in_table: 'sys_ux_client_script',
2564
- verification_timestamp: new Date().toISOString()
2565
- }
2353
+ script: response.data,
2354
+ message: `Client script '${args.name}' created for ${args.type} trigger`
2566
2355
  };
2567
2356
  }
2568
2357
  catch (error) {
@@ -2624,37 +2413,11 @@ ${configList}${layoutsText}${offlineText}
2624
2413
  if (!response.success) {
2625
2414
  throw new Error(`Failed to create event: ${response.error}`);
2626
2415
  }
2627
- // VERIFICATION: Confirm event was created
2628
- const sys_id = response.data.result.sys_id;
2629
- const verification = await this.client.getRecord('sys_ux_event', sys_id);
2630
- if (!verification.success) {
2631
- return {
2632
- success: false,
2633
- error: 'Event creation reported success but record not found in sys_ux_event table',
2634
- suggestion: 'Event creation may have been rolled back due to validation errors',
2635
- verification_failed: true
2636
- };
2637
- }
2638
- this.logger.info(`✅ UI Builder event created and verified: ${sys_id}`);
2416
+ this.logger.info('✅ UI Builder event created successfully');
2639
2417
  return {
2640
2418
  success: true,
2641
- verified: true,
2642
- event_sys_id: sys_id,
2643
- event_name: args.name,
2644
- event_scope: args.global_event ? 'Global' : 'Component Scoped',
2645
- component_scope: args.component_scope || 'Not specified',
2646
- created_at: new Date().toISOString(),
2647
- message: `✅ Custom event '${args.name}' created and verified successfully`,
2648
- detailed_confirmation: {
2649
- operation: 'CREATE UI Builder Event',
2650
- sys_id: sys_id,
2651
- name: args.name,
2652
- global_event: args.global_event || false,
2653
- bubbles: args.bubbles !== false,
2654
- cancelable: args.cancelable !== false,
2655
- verified_in_table: 'sys_ux_event',
2656
- verification_timestamp: new Date().toISOString()
2657
- }
2419
+ event: response.data,
2420
+ message: `Custom event '${args.name}' created ${args.global_event ? '(global)' : '(scoped)'}`
2658
2421
  };
2659
2422
  }
2660
2423
  catch (error) {
@@ -2934,55 +2697,18 @@ ${configList}${layoutsText}${offlineText}
2934
2697
  };
2935
2698
  }
2936
2699
  const result = await this.client.createRecord('sys_ux_experience', experienceData);
2937
- // ENHANCED FEEDBACK SYSTEM
2938
2700
  if (result.success && result.data && result.data.result && result.data.result.sys_id) {
2939
- const sys_id = result.data.result.sys_id;
2940
- // VERIFICATION: Confirm record actually exists
2941
- const verification = await this.client.getRecord('sys_ux_experience', sys_id);
2942
- if (!verification.success) {
2943
- return {
2944
- success: false,
2945
- error: `UX Experience creation reported success but record not found in sys_ux_experience table`,
2946
- suggestion: 'Record creation may have failed silently or been rolled back due to permissions',
2947
- reported_sys_id: sys_id,
2948
- verification_failed: true
2949
- };
2950
- }
2951
- 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}`);
2952
2702
  return {
2953
2703
  success: true,
2954
- verified: true,
2955
- experience_sys_id: sys_id,
2956
- experience_name: args.name,
2957
- shell_macroponent: shellSysId ? 'Linked to app shell' : 'No shell linked',
2958
- created_at: new Date().toISOString(),
2959
- table: 'sys_ux_experience',
2960
- message: `✅ UX Experience '${args.name}' created and verified successfully`,
2961
- detailed_confirmation: {
2962
- operation: 'CREATE UX Experience',
2963
- sys_id: sys_id,
2964
- name: args.name,
2965
- active: true,
2966
- verified_in_table: 'sys_ux_experience',
2967
- verification_timestamp: new Date().toISOString()
2968
- },
2969
- 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"
2970
2707
  };
2971
2708
  }
2972
2709
  else {
2973
2710
  const error = (result.data && result.data.error) || (result.error) || 'Unknown error creating experience';
2974
- return {
2975
- success: false,
2976
- error: `Failed to create UX Experience: ${error}`,
2977
- suggestion: this.getErrorSuggestion(error),
2978
- operation_attempted: 'CREATE sys_ux_experience',
2979
- debug_info: {
2980
- result_success: result.success,
2981
- has_data: !!(result.data),
2982
- has_result: !!(result.data && result.data.result),
2983
- has_sys_id: !!(result.data && result.data.result && result.data.result.sys_id)
2984
- }
2985
- };
2711
+ throw new Error(`Failed to create experience: ${error}`);
2986
2712
  }
2987
2713
  }
2988
2714
  catch (error) {
@@ -3024,43 +2750,17 @@ ${configList}${layoutsText}${offlineText}
3024
2750
  };
3025
2751
  const result = await this.client.createRecord('sys_ux_app_config', configData);
3026
2752
  if (result.success && result.data && result.data.result && result.data.result.sys_id) {
3027
- const sys_id = result.data.result.sys_id;
3028
- // VERIFICATION: Confirm app config was created
3029
- const verification = await this.client.getRecord('sys_ux_app_config', sys_id);
3030
- if (!verification.success) {
3031
- return {
3032
- success: false,
3033
- error: 'App config creation reported success but record not found in sys_ux_app_config table',
3034
- verification_failed: true
3035
- };
3036
- }
3037
- 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}`);
3038
2754
  return {
3039
2755
  success: true,
3040
- verified: true,
3041
- app_config_sys_id: sys_id,
3042
- config_name: args.name,
3043
- linked_experience: args.experience_sys_id,
3044
- created_at: new Date().toISOString(),
3045
- message: `✅ App Configuration '${args.name}' created and verified successfully`,
3046
- detailed_confirmation: {
3047
- operation: 'CREATE UX App Config',
3048
- sys_id: sys_id,
3049
- name: args.name,
3050
- experience_assoc: args.experience_sys_id,
3051
- verified_in_table: 'sys_ux_app_config',
3052
- verification_timestamp: new Date().toISOString()
3053
- },
3054
- 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"
3055
2759
  };
3056
2760
  }
3057
2761
  else {
3058
2762
  const error = (result.data && result.data.error) || (result.error) || 'Unknown error creating app config';
3059
- return {
3060
- success: false,
3061
- error: `Failed to create app config: ${error}`,
3062
- suggestion: this.getErrorSuggestion(error)
3063
- };
2763
+ throw new Error(`Failed to create app config: ${error}`);
3064
2764
  }
3065
2765
  }
3066
2766
  catch (error) {
@@ -3616,216 +3316,6 @@ ${configList}${layoutsText}${offlineText}
3616
3316
  throw error;
3617
3317
  }
3618
3318
  }
3619
- /**
3620
- * COMPREHENSIVE TOOL HEALTH TESTING
3621
- * Tests all workspace tools and provides detailed status report
3622
- */
3623
- async testAllWorkspaceTools(args) {
3624
- try {
3625
- this.logger.info('🛠️ Starting comprehensive tool health test...');
3626
- const testResults = {
3627
- test_timestamp: new Date().toISOString(),
3628
- tools_tested: 0,
3629
- tools_working: 0,
3630
- tools_failing: 0,
3631
- tools_unclear: 0,
3632
- detailed_results: [],
3633
- plugin_status: {},
3634
- recommendations: []
3635
- };
3636
- // Test critical plugins first
3637
- const pluginTests = [
3638
- { name: 'UI Builder', table: 'sys_ux_page', description: 'UI Builder functionality' },
3639
- { name: 'Now Experience Framework', table: 'sys_ux_experience', description: 'UX Workspace creation' },
3640
- { name: 'Agent Workspace', table: 'sys_ux_app_route', description: 'Configurable Agent Workspaces' },
3641
- { name: 'Mobile Publishing', table: 'sys_push_notif_msg', description: 'Mobile app management' },
3642
- { name: 'Flow Designer', table: 'sys_hub_flow', description: 'Flow automation' }
3643
- ];
3644
- for (const plugin of pluginTests) {
3645
- const pluginTest = await this.client.searchRecords(plugin.table, '', 1);
3646
- testResults.plugin_status[plugin.name] = {
3647
- available: pluginTest.success,
3648
- table: plugin.table,
3649
- description: plugin.description,
3650
- status: pluginTest.success ? '✅ Available' : '❌ Not Available'
3651
- };
3652
- }
3653
- // Test individual tools
3654
- const toolTests = [
3655
- // UX Experience tools
3656
- {
3657
- name: 'snow_create_ux_experience',
3658
- test: () => this.snow_create_ux_experience({ name: 'Health Test Experience' }),
3659
- category: 'UX Experience',
3660
- expects_sys_id: true
3661
- },
3662
- // UI Builder tools
3663
- {
3664
- name: 'snow_discover_uib_pages',
3665
- test: () => this.discoverUIBuilderPages({}),
3666
- category: 'UI Builder',
3667
- expects_sys_id: false
3668
- },
3669
- // Mobile tools
3670
- {
3671
- name: 'snow_configure_mobile_app',
3672
- test: () => this.configureMobileApp({ app_name: 'Health Test App' }),
3673
- category: 'Mobile',
3674
- expects_sys_id: true
3675
- }
3676
- ];
3677
- for (const toolTest of toolTests) {
3678
- try {
3679
- testResults.tools_tested++;
3680
- const testStart = Date.now();
3681
- const result = await toolTest.test();
3682
- const testDuration = Date.now() - testStart;
3683
- let status = '❌ FAILED';
3684
- let feedback = 'No response';
3685
- if (result && result.success === true) {
3686
- if (toolTest.expects_sys_id && result.sys_id) {
3687
- status = '✅ WORKING';
3688
- feedback = `Created record with sys_id: ${result.sys_id}`;
3689
- testResults.tools_working++;
3690
- }
3691
- else if (!toolTest.expects_sys_id) {
3692
- status = '✅ WORKING';
3693
- feedback = 'Operation completed successfully';
3694
- testResults.tools_working++;
3695
- }
3696
- else {
3697
- status = '⚠️ UNCLEAR';
3698
- feedback = 'Success reported but no sys_id returned';
3699
- testResults.tools_unclear++;
3700
- }
3701
- }
3702
- else if (result && result.success === false) {
3703
- status = '❌ FAILED';
3704
- feedback = result.error || 'Unknown error';
3705
- testResults.tools_failing++;
3706
- }
3707
- else {
3708
- status = '⚠️ UNCLEAR';
3709
- feedback = 'No clear success/failure indication';
3710
- testResults.tools_unclear++;
3711
- }
3712
- testResults.detailed_results.push({
3713
- tool: toolTest.name,
3714
- category: toolTest.category,
3715
- status: status,
3716
- feedback: feedback,
3717
- execution_time_ms: testDuration,
3718
- expects_sys_id: toolTest.expects_sys_id,
3719
- actual_result: result
3720
- });
3721
- }
3722
- catch (error) {
3723
- testResults.tools_tested++;
3724
- testResults.tools_failing++;
3725
- testResults.detailed_results.push({
3726
- tool: toolTest.name,
3727
- category: toolTest.category,
3728
- status: '❌ FAILED',
3729
- feedback: `Exception: ${error}`,
3730
- execution_time_ms: 0,
3731
- error_type: 'EXCEPTION'
3732
- });
3733
- }
3734
- }
3735
- // Generate recommendations
3736
- if (testResults.tools_working === 0) {
3737
- testResults.recommendations.push('No tools are working - check authentication and instance setup');
3738
- }
3739
- if (testResults.tools_unclear > 0) {
3740
- testResults.recommendations.push('Some tools have unclear status - implement better response validation');
3741
- }
3742
- this.logger.info(`✅ Tool health test completed: ${testResults.tools_working}/${testResults.tools_tested} working`);
3743
- return {
3744
- success: true,
3745
- test_summary: testResults,
3746
- message: `Tool health test completed: ${testResults.tools_working}/${testResults.tools_tested} tools working properly`,
3747
- detailed_report: testResults.detailed_results
3748
- };
3749
- }
3750
- catch (error) {
3751
- this.logger.error('Failed to test workspace tools:', error);
3752
- throw error;
3753
- }
3754
- }
3755
- /**
3756
- * CHECK PLUGIN AVAILABILITY
3757
- * Comprehensive plugin and licensing status check
3758
- */
3759
- async checkPluginAvailability(args) {
3760
- try {
3761
- this.logger.info('🔌 Checking ServiceNow plugin availability...');
3762
- const pluginChecks = [];
3763
- if (args.check_ui_builder) {
3764
- const uiBuilderCheck = await this.client.searchRecords('sys_ux_page', '', 1);
3765
- pluginChecks.push({
3766
- name: 'UI Builder',
3767
- table: 'sys_ux_page',
3768
- available: uiBuilderCheck.success,
3769
- error: uiBuilderCheck.success ? null : uiBuilderCheck.error,
3770
- status: uiBuilderCheck.success ? '✅ Available' : '❌ Not Available',
3771
- recommendation: uiBuilderCheck.success ? 'UI Builder tools should work' : 'Install UI Builder plugin from ServiceNow Store'
3772
- });
3773
- }
3774
- if (args.check_uxf) {
3775
- const uxfCheck = await this.client.searchRecords('sys_ux_experience', '', 1);
3776
- pluginChecks.push({
3777
- name: 'Now Experience Framework',
3778
- table: 'sys_ux_experience',
3779
- available: uxfCheck.success,
3780
- error: uxfCheck.success ? null : uxfCheck.error,
3781
- status: uxfCheck.success ? '✅ Available' : '❌ Not Available',
3782
- recommendation: uxfCheck.success ? 'UX workspace creation should work' : 'Enable Now Experience Framework in instance'
3783
- });
3784
- }
3785
- if (args.check_agent_workspace) {
3786
- const agentCheck = await this.client.searchRecords('sys_ux_screen_type', '', 1);
3787
- pluginChecks.push({
3788
- name: 'Agent Workspace',
3789
- table: 'sys_ux_screen_type',
3790
- available: agentCheck.success,
3791
- error: agentCheck.success ? null : agentCheck.error,
3792
- status: agentCheck.success ? '✅ Available' : '❌ Not Available',
3793
- recommendation: agentCheck.success ? 'Agent workspace tools should work' : 'Install Agent Workspace plugin'
3794
- });
3795
- }
3796
- if (args.check_mobile) {
3797
- const mobileCheck = await this.client.searchRecords('sys_push_notif_msg', '', 1);
3798
- pluginChecks.push({
3799
- name: 'Mobile Publishing',
3800
- table: 'sys_push_notif_msg',
3801
- available: mobileCheck.success,
3802
- error: mobileCheck.success ? null : mobileCheck.error,
3803
- status: mobileCheck.success ? '✅ Available' : '❌ Not Available',
3804
- recommendation: mobileCheck.success ? 'Mobile tools should work' : 'Install Mobile Publishing plugin (requires additional licensing)'
3805
- });
3806
- }
3807
- const availableCount = pluginChecks.filter(p => p.available).length;
3808
- const totalCount = pluginChecks.length;
3809
- this.logger.info(`✅ Plugin check completed: ${availableCount}/${totalCount} plugins available`);
3810
- return {
3811
- success: true,
3812
- plugin_summary: {
3813
- total_checked: totalCount,
3814
- available: availableCount,
3815
- unavailable: totalCount - availableCount,
3816
- percentage: Math.round((availableCount / totalCount) * 100)
3817
- },
3818
- plugins: pluginChecks,
3819
- message: `Plugin availability check: ${availableCount}/${totalCount} plugins available`,
3820
- overall_status: availableCount === totalCount ? 'All plugins available' :
3821
- availableCount > 0 ? 'Partial plugin availability' : 'No plugins available'
3822
- };
3823
- }
3824
- catch (error) {
3825
- this.logger.error('Failed to check plugin availability:', error);
3826
- throw error;
3827
- }
3828
- }
3829
3319
  /**
3830
3320
  * CONFIGURABLE AGENT WORKSPACE: Create using UX App architecture
3831
3321
  */
@@ -3932,141 +3422,6 @@ ${configList}${layoutsText}${offlineText}
3932
3422
  .replace(/^-|-$/g, '') // Trim leading/trailing hyphens
3933
3423
  .substring(0, 80); // Max 80 chars (ServiceNow field limit)
3934
3424
  }
3935
- /**
3936
- * ENHANCED RESPONSE VALIDATION SYSTEM
3937
- * Provides comprehensive feedback for all tool operations
3938
- */
3939
- async validateAndConfirmOperation(operationType, result, details) {
3940
- try {
3941
- // Standard validation for ServiceNow API responses
3942
- if (!result || typeof result !== 'object') {
3943
- return {
3944
- success: false,
3945
- error: `No response received from ServiceNow API for ${operationType}`,
3946
- suggestion: 'Check ServiceNow instance connectivity and authentication',
3947
- validation_result: 'NO_RESPONSE'
3948
- };
3949
- }
3950
- // Check for API success/failure
3951
- if (result.success === false) {
3952
- return {
3953
- success: false,
3954
- error: result.error || `${operationType} operation failed`,
3955
- suggestion: this.getErrorSuggestion(result.error || ''),
3956
- validation_result: 'API_FAILURE'
3957
- };
3958
- }
3959
- // Validate response data structure
3960
- if (result.success && (!result.data || !result.data.result)) {
3961
- return {
3962
- success: false,
3963
- error: `${operationType} succeeded but returned invalid data structure`,
3964
- suggestion: 'Check ServiceNow table permissions and field access',
3965
- validation_result: 'INVALID_DATA_STRUCTURE'
3966
- };
3967
- }
3968
- // Extract sys_id for verification
3969
- const sys_id = result.data?.result?.sys_id;
3970
- if (result.success && !sys_id) {
3971
- return {
3972
- success: false,
3973
- error: `${operationType} succeeded but no sys_id returned`,
3974
- suggestion: 'Record may have been created but sys_id is not accessible',
3975
- validation_result: 'MISSING_SYS_ID'
3976
- };
3977
- }
3978
- // VERIFICATION STEP: Confirm record actually exists
3979
- if (sys_id && details.table) {
3980
- const verification = await this.client.getRecord(details.table, sys_id);
3981
- if (!verification.success) {
3982
- return {
3983
- success: false,
3984
- error: `${operationType} reported success but record not found in ${details.table}`,
3985
- suggestion: 'Record creation may have failed silently or been rolled back',
3986
- validation_result: 'RECORD_NOT_FOUND',
3987
- reported_sys_id: sys_id
3988
- };
3989
- }
3990
- // SUCCESS with verification!
3991
- return {
3992
- success: true,
3993
- sys_id: sys_id,
3994
- verified: true,
3995
- operation_type: operationType,
3996
- table: details.table,
3997
- message: `${operationType} completed successfully`,
3998
- confirmation: `Record verified in ${details.table} with sys_id: ${sys_id}`,
3999
- validation_result: 'VERIFIED_SUCCESS'
4000
- };
4001
- }
4002
- // Success without verification (no sys_id or table)
4003
- return {
4004
- success: true,
4005
- operation_type: operationType,
4006
- message: `${operationType} completed`,
4007
- validation_result: 'SUCCESS_NO_VERIFICATION'
4008
- };
4009
- }
4010
- catch (error) {
4011
- this.logger.error('Validation error:', error);
4012
- return {
4013
- success: false,
4014
- error: `Validation failed for ${operationType}: ${error}`,
4015
- suggestion: 'Check ServiceNow connectivity and permissions',
4016
- validation_result: 'VALIDATION_ERROR'
4017
- };
4018
- }
4019
- }
4020
- /**
4021
- * Get actionable suggestions based on error type
4022
- */
4023
- getErrorSuggestion(error) {
4024
- const errorLower = error.toLowerCase();
4025
- if (errorLower.includes('403') || errorLower.includes('forbidden')) {
4026
- return 'Check user permissions. May need ui_builder_admin or workspace_admin roles.';
4027
- }
4028
- if (errorLower.includes('404') || errorLower.includes('not found')) {
4029
- return 'Table/endpoint not available. Check if required plugin is installed and activated.';
4030
- }
4031
- if (errorLower.includes('400') || errorLower.includes('bad request')) {
4032
- return 'Invalid parameters or missing required fields. Check API documentation.';
4033
- }
4034
- if (errorLower.includes('401') || errorLower.includes('unauthorized')) {
4035
- return 'Authentication issue. Run snow-flow auth login to re-authenticate.';
4036
- }
4037
- if (errorLower.includes('plugin') || errorLower.includes('license')) {
4038
- return 'Required plugin not installed. Check ServiceNow Store for required plugins.';
4039
- }
4040
- return 'Check ServiceNow system logs for detailed error information.';
4041
- }
4042
- /**
4043
- * Enhanced tool execution wrapper with comprehensive feedback
4044
- */
4045
- async executeWithFeedback(operationType, operation, details) {
4046
- try {
4047
- this.logger.info(`🔄 Executing ${operationType}...`);
4048
- const startTime = Date.now();
4049
- const result = await operation();
4050
- const executionTime = Date.now() - startTime;
4051
- const validation = await this.validateAndConfirmOperation(operationType, result, details);
4052
- return {
4053
- ...validation,
4054
- execution_time_ms: executionTime,
4055
- timestamp: new Date().toISOString()
4056
- };
4057
- }
4058
- catch (error) {
4059
- this.logger.error(`❌ ${operationType} failed:`, error);
4060
- return {
4061
- success: false,
4062
- operation_type: operationType,
4063
- error: error instanceof Error ? error.message : String(error),
4064
- suggestion: this.getErrorSuggestion(String(error)),
4065
- validation_result: 'EXECUTION_ERROR',
4066
- timestamp: new Date().toISOString()
4067
- };
4068
- }
4069
- }
4070
3425
  /**
4071
3426
  * Validate workspace configuration (fix from user feedback)
4072
3427
  */
@@ -4086,9 +3441,32 @@ ${configList}${layoutsText}${offlineText}
4086
3441
  return errors;
4087
3442
  }
4088
3443
  async run() {
4089
- const transport = new stdio_js_1.StdioServerTransport();
4090
- await this.server.connect(transport);
4091
- 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
+ }
4092
3470
  }
4093
3471
  }
4094
3472
  const server = new ServiceNowFlowWorkspaceMobileMCP();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "4.5.50",
3
+ "version": "4.5.52",
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",