snow-flow 3.3.6 → 3.3.8
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/.mcp.json.template
CHANGED
|
@@ -131,6 +131,18 @@
|
|
|
131
131
|
"SNOW_CLIENT_ID": "{{SNOW_CLIENT_ID}}",
|
|
132
132
|
"SNOW_CLIENT_SECRET": "{{SNOW_CLIENT_SECRET}}"
|
|
133
133
|
}
|
|
134
|
+
},
|
|
135
|
+
"servicenow-system-properties": {
|
|
136
|
+
"command": "node",
|
|
137
|
+
"args": [
|
|
138
|
+
"{{PROJECT_ROOT}}/dist/mcp/servicenow-system-properties-mcp.js"
|
|
139
|
+
],
|
|
140
|
+
"description": "System property management via official ServiceNow APIs: get/set/list/delete properties, bulk operations, import/export JSON, validate values, search, categories, audit history - all using standard Table API on sys_properties",
|
|
141
|
+
"env": {
|
|
142
|
+
"SNOW_INSTANCE": "{{SNOW_INSTANCE}}",
|
|
143
|
+
"SNOW_CLIENT_ID": "{{SNOW_CLIENT_ID}}",
|
|
144
|
+
"SNOW_CLIENT_SECRET": "{{SNOW_CLIENT_SECRET}}"
|
|
145
|
+
}
|
|
134
146
|
}
|
|
135
147
|
}
|
|
136
148
|
}
|
package/dist/dynamic-version.js
CHANGED
|
@@ -36,7 +36,7 @@ function getDynamicVersion() {
|
|
|
36
36
|
console.warn('Warning: Could not read version from package.json:', error);
|
|
37
37
|
}
|
|
38
38
|
// Fallback to hardcoded version
|
|
39
|
-
return '3.3.
|
|
39
|
+
return '3.3.8';
|
|
40
40
|
}
|
|
41
41
|
// Export a constant that uses the dynamic version
|
|
42
42
|
exports.VERSION = getDynamicVersion();
|
|
@@ -1316,7 +1316,12 @@ ${is403Error ? '\n⚠️ **Possible False Negative**: Widget may have been crea
|
|
|
1316
1316
|
const { updateSetId, updateSetName } = await this.ensureUpdateSet('Portal Page', args.page_id);
|
|
1317
1317
|
// Validate portal page structure
|
|
1318
1318
|
if (!args.page_id || !args.title) {
|
|
1319
|
-
|
|
1319
|
+
this.logger.error('Portal page validation failed', {
|
|
1320
|
+
args,
|
|
1321
|
+
hasPageId: !!args.page_id,
|
|
1322
|
+
hasTitle: !!args.title
|
|
1323
|
+
});
|
|
1324
|
+
throw new Error(`Portal page must have page_id and title. Received: page_id=${args.page_id}, title=${args.title}`);
|
|
1320
1325
|
}
|
|
1321
1326
|
// Find widget sys_id if widget name is provided
|
|
1322
1327
|
let widgetSysId = args.widget_sys_id;
|
|
@@ -1337,18 +1342,22 @@ ${is403Error ? '\n⚠️ **Possible False Negative**: Widget may have been crea
|
|
|
1337
1342
|
}
|
|
1338
1343
|
}
|
|
1339
1344
|
// Determine portal sys_id
|
|
1340
|
-
let portalSysId = '';
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
this.
|
|
1345
|
+
let portalSysId = args.sp_portal || '';
|
|
1346
|
+
// If sp_portal is already a sys_id (32 char hex), use it directly
|
|
1347
|
+
if (!/^[a-f0-9]{32}$/.test(portalSysId)) {
|
|
1348
|
+
// Not a sys_id, try to look it up
|
|
1349
|
+
try {
|
|
1350
|
+
// Default to Employee Service Portal if available, otherwise standard Service Portal
|
|
1351
|
+
const portalQuery = args.portal === 'esc' ? 'url_suffix=esc' : 'url_suffix=sp';
|
|
1352
|
+
const portalResult = await this.client.searchRecords('sp_portal', portalQuery, 1);
|
|
1353
|
+
if (portalResult.success && portalResult.data?.result?.length > 0) {
|
|
1354
|
+
portalSysId = portalResult.data.result[0].sys_id;
|
|
1355
|
+
this.logger.info('Found portal', { portal: args.portal, sys_id: portalSysId });
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
catch (error) {
|
|
1359
|
+
this.logger.warn('Failed to lookup portal, using provided value', { portal: args.portal, error });
|
|
1348
1360
|
}
|
|
1349
|
-
}
|
|
1350
|
-
catch (error) {
|
|
1351
|
-
this.logger.warn('Failed to lookup portal, using default', { portal: args.portal, error });
|
|
1352
1361
|
}
|
|
1353
1362
|
// Create portal page
|
|
1354
1363
|
let pageResult;
|
|
@@ -1381,8 +1390,35 @@ ${is403Error ? '\n⚠️ **Possible False Negative**: Widget may have been crea
|
|
|
1381
1390
|
const credentials = await this.oauth.loadCredentials();
|
|
1382
1391
|
// Create widget instances on the page if widget is provided
|
|
1383
1392
|
const widgetInstances = [];
|
|
1384
|
-
|
|
1385
|
-
|
|
1393
|
+
// Support both widgets array and single widget
|
|
1394
|
+
const widgetsToCreate = args.widgets || [];
|
|
1395
|
+
// If no widgets array but a single widget is specified, create one widget
|
|
1396
|
+
if (widgetsToCreate.length === 0 && widgetSysId) {
|
|
1397
|
+
widgetsToCreate.push({
|
|
1398
|
+
widget: args.widget_name || widgetSysId,
|
|
1399
|
+
width: 12,
|
|
1400
|
+
row: 1,
|
|
1401
|
+
column: 1,
|
|
1402
|
+
title: args.widget_title || args.title || '',
|
|
1403
|
+
options: args.widget_options || {}
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
if (widgetsToCreate.length > 0) {
|
|
1407
|
+
for (const widgetConfig of widgetsToCreate) {
|
|
1408
|
+
// Determine widget sys_id for this widget
|
|
1409
|
+
let currentWidgetSysId = widgetSysId; // Default to the main widget
|
|
1410
|
+
// If widget config specifies a different widget, look it up
|
|
1411
|
+
if (widgetConfig.widget && widgetConfig.widget !== args.widget_name) {
|
|
1412
|
+
try {
|
|
1413
|
+
const widgetLookup = await this.client.searchRecords('sp_widget', `sys_id=${widgetConfig.widget}^ORname=${widgetConfig.widget}`, 1);
|
|
1414
|
+
if (widgetLookup.success && widgetLookup.data?.result?.length > 0) {
|
|
1415
|
+
currentWidgetSysId = widgetLookup.data.result[0].sys_id;
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
catch (lookupError) {
|
|
1419
|
+
this.logger.warn('Could not find widget, using default', { widget: widgetConfig.widget });
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1386
1422
|
try {
|
|
1387
1423
|
// Create container
|
|
1388
1424
|
const containerResult = await this.client.createRecord('sp_container', {
|
|
@@ -1417,10 +1453,10 @@ ${is403Error ? '\n⚠️ **Possible False Negative**: Widget may have been crea
|
|
|
1417
1453
|
// Create widget instance
|
|
1418
1454
|
const instanceResult = await this.client.createRecord('sp_instance', {
|
|
1419
1455
|
sp_column: columnResult.data.sys_id,
|
|
1420
|
-
sp_widget:
|
|
1456
|
+
sp_widget: currentWidgetSysId, // Use the current widget sys_id, not the main one
|
|
1421
1457
|
order: widgetConfig.order || 100,
|
|
1422
1458
|
title: widgetConfig.title || '',
|
|
1423
|
-
options: JSON.stringify(widgetConfig.options || {}),
|
|
1459
|
+
options: JSON.stringify(widgetConfig.options || widgetConfig.widget_parameters || {}),
|
|
1424
1460
|
class_name: widgetConfig.instance_class || '',
|
|
1425
1461
|
color: widgetConfig.color || 'default',
|
|
1426
1462
|
active: true,
|
|
@@ -7260,7 +7296,23 @@ Use individual deployment tools like \`snow_deploy_${args.type}\` with manual co
|
|
|
7260
7296
|
case 'widget':
|
|
7261
7297
|
return await this.deployWidget(scopedConfig);
|
|
7262
7298
|
case 'portal_page':
|
|
7263
|
-
|
|
7299
|
+
// Map config fields to expected parameter names for portal_page
|
|
7300
|
+
const portalPageArgs = {
|
|
7301
|
+
page_id: scopedConfig.id || scopedConfig.page_id,
|
|
7302
|
+
title: scopedConfig.title,
|
|
7303
|
+
widget_name: scopedConfig.widget_name,
|
|
7304
|
+
widget_sys_id: scopedConfig.widget_sys_id,
|
|
7305
|
+
description: scopedConfig.summary || scopedConfig.description,
|
|
7306
|
+
page_css: scopedConfig.css,
|
|
7307
|
+
portal: scopedConfig.portal || scopedConfig.sp_portal || 'sp',
|
|
7308
|
+
public: scopedConfig.public !== undefined ? scopedConfig.public : true,
|
|
7309
|
+
requires_authentication: scopedConfig.requires_authentication,
|
|
7310
|
+
draft: scopedConfig.draft || false,
|
|
7311
|
+
// Map containers to widgets format
|
|
7312
|
+
widgets: this.mapContainersToWidgets(scopedConfig.containers),
|
|
7313
|
+
...scopedConfig // Include any other fields
|
|
7314
|
+
};
|
|
7315
|
+
return await this.deployPortalPage(portalPageArgs);
|
|
7264
7316
|
case 'application':
|
|
7265
7317
|
return await this.deployApplication(scopedConfig);
|
|
7266
7318
|
case 'xml_update_set':
|
|
@@ -8851,6 +8903,36 @@ c.$onInit = function() {
|
|
|
8851
8903
|
await this.server.connect(transport);
|
|
8852
8904
|
this.logger.info('ServiceNow Deployment MCP Server started');
|
|
8853
8905
|
}
|
|
8906
|
+
/**
|
|
8907
|
+
* Map container structure to widget structure for portal page deployment
|
|
8908
|
+
*/
|
|
8909
|
+
mapContainersToWidgets(containers) {
|
|
8910
|
+
if (!containers || !Array.isArray(containers)) {
|
|
8911
|
+
return [];
|
|
8912
|
+
}
|
|
8913
|
+
const widgets = [];
|
|
8914
|
+
for (const container of containers) {
|
|
8915
|
+
if (container.widget_instance) {
|
|
8916
|
+
widgets.push({
|
|
8917
|
+
widget: container.widget_instance.widget,
|
|
8918
|
+
width: container.width || 12,
|
|
8919
|
+
row: container.row || 1,
|
|
8920
|
+
column: container.column || 1,
|
|
8921
|
+
title: container.widget_instance.title || '',
|
|
8922
|
+
options: container.widget_instance.widget_parameters || {},
|
|
8923
|
+
container_title: container.title || '',
|
|
8924
|
+
class_name: container.class_name || '',
|
|
8925
|
+
background_color: container.background_color || '',
|
|
8926
|
+
background_image: container.background_image || '',
|
|
8927
|
+
background_style: container.background_style || 'default',
|
|
8928
|
+
instance_class: container.widget_instance.class_name || '',
|
|
8929
|
+
color: container.widget_instance.color || 'default',
|
|
8930
|
+
order: container.widget_instance.order || 100
|
|
8931
|
+
});
|
|
8932
|
+
}
|
|
8933
|
+
}
|
|
8934
|
+
return widgets;
|
|
8935
|
+
}
|
|
8854
8936
|
/**
|
|
8855
8937
|
* Escape XML special characters
|
|
8856
8938
|
*/
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ServiceNow System Properties MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive system property management through official ServiceNow APIs
|
|
5
|
+
* Uses the standard Table API on sys_properties table
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* ServiceNow System Properties MCP Server
|
|
9
|
+
* Manages system properties through official ServiceNow REST APIs
|
|
10
|
+
*/
|
|
11
|
+
export declare class ServiceNowSystemPropertiesMCP {
|
|
12
|
+
private server;
|
|
13
|
+
private client;
|
|
14
|
+
private propertyCache;
|
|
15
|
+
constructor();
|
|
16
|
+
private setupHandlers;
|
|
17
|
+
private setupTools;
|
|
18
|
+
/**
|
|
19
|
+
* Get a system property value
|
|
20
|
+
*/
|
|
21
|
+
private getProperty;
|
|
22
|
+
/**
|
|
23
|
+
* Set or create a system property
|
|
24
|
+
*/
|
|
25
|
+
private setProperty;
|
|
26
|
+
/**
|
|
27
|
+
* List system properties
|
|
28
|
+
*/
|
|
29
|
+
private listProperties;
|
|
30
|
+
/**
|
|
31
|
+
* Delete a system property
|
|
32
|
+
*/
|
|
33
|
+
private deleteProperty;
|
|
34
|
+
/**
|
|
35
|
+
* Search properties
|
|
36
|
+
*/
|
|
37
|
+
private searchProperties;
|
|
38
|
+
/**
|
|
39
|
+
* Bulk get properties
|
|
40
|
+
*/
|
|
41
|
+
private bulkGetProperties;
|
|
42
|
+
/**
|
|
43
|
+
* Bulk set properties
|
|
44
|
+
*/
|
|
45
|
+
private bulkSetProperties;
|
|
46
|
+
/**
|
|
47
|
+
* Export properties
|
|
48
|
+
*/
|
|
49
|
+
private exportProperties;
|
|
50
|
+
/**
|
|
51
|
+
* Import properties
|
|
52
|
+
*/
|
|
53
|
+
private importProperties;
|
|
54
|
+
/**
|
|
55
|
+
* Validate property value
|
|
56
|
+
*/
|
|
57
|
+
private validateProperty;
|
|
58
|
+
/**
|
|
59
|
+
* Get property categories
|
|
60
|
+
*/
|
|
61
|
+
private getCategories;
|
|
62
|
+
/**
|
|
63
|
+
* Get property audit history
|
|
64
|
+
*/
|
|
65
|
+
private getPropertyHistory;
|
|
66
|
+
start(): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=servicenow-system-properties-mcp.d.ts.map
|