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
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
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
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2244
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2305
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2551
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2642
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
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.
|
|
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",
|