snow-flow 3.4.13 → 3.4.14
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/dist/cli.js +23 -51
- package/dist/mcp/servicenow-automation-mcp.js +65 -29
- package/dist/mcp/servicenow-change-virtualagent-pa-mcp.js +51 -21
- package/dist/mcp/servicenow-cmdb-event-hr-csm-devops-mcp.js +59 -25
- package/dist/mcp/servicenow-deployment-mcp.js +38 -16
- package/dist/mcp/servicenow-development-assistant-mcp.js +67 -31
- package/dist/mcp/servicenow-flow-workspace-mobile-mcp.js +53 -22
- package/dist/mcp/servicenow-integration-mcp.js +48 -12
- package/dist/mcp/servicenow-knowledge-catalog-mcp.js +42 -16
- package/dist/mcp/servicenow-machine-learning-mcp.js +44 -17
- package/dist/mcp/servicenow-operations-mcp.d.ts +1 -0
- package/dist/mcp/servicenow-operations-mcp.js +108 -79
- package/dist/mcp/servicenow-platform-development-mcp.js +42 -11
- package/dist/mcp/servicenow-reporting-analytics-mcp.js +36 -13
- package/dist/mcp/servicenow-security-compliance-mcp.js +35 -13
- package/dist/mcp/servicenow-system-properties-mcp.d.ts +1 -0
- package/dist/mcp/servicenow-system-properties-mcp.js +66 -42
- package/dist/mcp/servicenow-update-set-mcp.js +35 -11
- package/package.json +1 -1
|
@@ -11,9 +11,8 @@ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
|
11
11
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
12
12
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
13
13
|
const servicenow_client_js_1 = require("../utils/servicenow-client.js");
|
|
14
|
-
const
|
|
14
|
+
const mcp_logger_js_1 = require("./shared/mcp-logger.js");
|
|
15
15
|
const snow_oauth_js_1 = require("../utils/snow-oauth.js");
|
|
16
|
-
const logger = new logger_js_1.Logger('ServiceNowSystemProperties');
|
|
17
16
|
/**
|
|
18
17
|
* ServiceNow System Properties MCP Server
|
|
19
18
|
* Manages system properties through official ServiceNow REST APIs
|
|
@@ -31,6 +30,7 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
31
30
|
});
|
|
32
31
|
this.client = new servicenow_client_js_1.ServiceNowClient();
|
|
33
32
|
this.oauth = new snow_oauth_js_1.SnowOAuth();
|
|
33
|
+
this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowSystemProperties');
|
|
34
34
|
this.setupHandlers();
|
|
35
35
|
this.setupTools();
|
|
36
36
|
}
|
|
@@ -319,42 +319,60 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
319
319
|
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
320
320
|
const { name, arguments: args } = request.params;
|
|
321
321
|
try {
|
|
322
|
+
// Start operation with token tracking
|
|
323
|
+
this.logger.operationStart(name, args);
|
|
322
324
|
// Ensure authentication
|
|
323
325
|
const isAuthenticated = await this.oauth.isAuthenticated();
|
|
324
326
|
if (!isAuthenticated) {
|
|
325
327
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, 'Not authenticated. Please run "snow-flow auth login" first.');
|
|
326
328
|
}
|
|
329
|
+
let result;
|
|
327
330
|
switch (name) {
|
|
328
331
|
case 'snow_property_get':
|
|
329
|
-
|
|
332
|
+
result = await this.getProperty(args);
|
|
333
|
+
break;
|
|
330
334
|
case 'snow_property_set':
|
|
331
|
-
|
|
335
|
+
result = await this.setProperty(args);
|
|
336
|
+
break;
|
|
332
337
|
case 'snow_property_list':
|
|
333
|
-
|
|
338
|
+
result = await this.listProperties(args);
|
|
339
|
+
break;
|
|
334
340
|
case 'snow_property_delete':
|
|
335
|
-
|
|
341
|
+
result = await this.deleteProperty(args);
|
|
342
|
+
break;
|
|
336
343
|
case 'snow_property_search':
|
|
337
|
-
|
|
344
|
+
result = await this.searchProperties(args);
|
|
345
|
+
break;
|
|
338
346
|
case 'snow_property_bulk_get':
|
|
339
|
-
|
|
347
|
+
result = await this.bulkGetProperties(args);
|
|
348
|
+
break;
|
|
340
349
|
case 'snow_property_bulk_set':
|
|
341
|
-
|
|
350
|
+
result = await this.bulkSetProperties(args);
|
|
351
|
+
break;
|
|
342
352
|
case 'snow_property_export':
|
|
343
|
-
|
|
353
|
+
result = await this.exportProperties(args);
|
|
354
|
+
break;
|
|
344
355
|
case 'snow_property_import':
|
|
345
|
-
|
|
356
|
+
result = await this.importProperties(args);
|
|
357
|
+
break;
|
|
346
358
|
case 'snow_property_validate':
|
|
347
|
-
|
|
359
|
+
result = await this.validateProperty(args);
|
|
360
|
+
break;
|
|
348
361
|
case 'snow_property_categories':
|
|
349
|
-
|
|
362
|
+
result = await this.getCategories(args);
|
|
363
|
+
break;
|
|
350
364
|
case 'snow_property_history':
|
|
351
|
-
|
|
365
|
+
result = await this.getPropertyHistory(args);
|
|
366
|
+
break;
|
|
352
367
|
default:
|
|
353
368
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
354
369
|
}
|
|
370
|
+
// Complete operation with token tracking
|
|
371
|
+
this.logger.operationComplete(name, result);
|
|
372
|
+
return result;
|
|
355
373
|
}
|
|
356
374
|
catch (error) {
|
|
357
|
-
logger.error(`Tool execution failed: ${name}`, error);
|
|
375
|
+
this.logger.error(`Tool execution failed: ${name}`, error);
|
|
358
376
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, error instanceof Error ? error.message : String(error));
|
|
359
377
|
}
|
|
360
378
|
});
|
|
@@ -364,8 +382,9 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
364
382
|
*/
|
|
365
383
|
async getProperty(args) {
|
|
366
384
|
const { name, include_metadata = false } = args;
|
|
367
|
-
logger.info(`Getting property: ${name}`);
|
|
385
|
+
this.logger.info(`Getting property: ${name}`);
|
|
368
386
|
try {
|
|
387
|
+
this.logger.trackAPICall('SEARCH', 'sys_properties', 1);
|
|
369
388
|
const response = await this.client.searchRecords('sys_properties', `name=${name}`, 1);
|
|
370
389
|
if (!response.success || !response.data?.result?.length) {
|
|
371
390
|
return {
|
|
@@ -406,7 +425,7 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
406
425
|
}
|
|
407
426
|
}
|
|
408
427
|
catch (error) {
|
|
409
|
-
logger.error('Failed to get property:', error);
|
|
428
|
+
this.logger.error('Failed to get property:', error);
|
|
410
429
|
throw error;
|
|
411
430
|
}
|
|
412
431
|
}
|
|
@@ -415,14 +434,16 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
415
434
|
*/
|
|
416
435
|
async setProperty(args) {
|
|
417
436
|
const { name, value, description, type = 'string', choices, is_private = false, suffix } = args;
|
|
418
|
-
logger.info(`Setting property: ${name} = ${value}`);
|
|
437
|
+
this.logger.info(`Setting property: ${name} = ${value}`);
|
|
419
438
|
try {
|
|
420
439
|
// Check if property exists
|
|
440
|
+
this.logger.trackAPICall('SEARCH', 'sys_properties', 1);
|
|
421
441
|
const existing = await this.client.searchRecords('sys_properties', `name=${name}`, 1);
|
|
422
442
|
let result;
|
|
423
443
|
if (existing.success && existing.data?.result?.length > 0) {
|
|
424
444
|
// Update existing property
|
|
425
445
|
const sys_id = existing.data.result[0].sys_id;
|
|
446
|
+
this.logger.trackAPICall('UPDATE', 'sys_properties', 1);
|
|
426
447
|
result = await this.client.updateRecord('sys_properties', sys_id, {
|
|
427
448
|
value,
|
|
428
449
|
...(description && { description }),
|
|
@@ -431,10 +452,11 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
431
452
|
...(suffix && { suffix }),
|
|
432
453
|
is_private: is_private ? 'true' : 'false'
|
|
433
454
|
});
|
|
434
|
-
logger.info(`Updated property: ${name}`);
|
|
455
|
+
this.logger.info(`Updated property: ${name}`);
|
|
435
456
|
}
|
|
436
457
|
else {
|
|
437
458
|
// Create new property
|
|
459
|
+
this.logger.trackAPICall('CREATE', 'sys_properties', 1);
|
|
438
460
|
result = await this.client.createRecord('sys_properties', {
|
|
439
461
|
name,
|
|
440
462
|
value,
|
|
@@ -444,7 +466,7 @@ class ServiceNowSystemPropertiesMCP {
|
|
|
444
466
|
is_private: is_private ? 'true' : 'false',
|
|
445
467
|
suffix: suffix || 'global'
|
|
446
468
|
});
|
|
447
|
-
logger.info(`Created new property: ${name}`);
|
|
469
|
+
this.logger.info(`Created new property: ${name}`);
|
|
448
470
|
}
|
|
449
471
|
if (!result.success) {
|
|
450
472
|
throw new Error(`Failed to set property: ${result.error}`);
|
|
@@ -468,7 +490,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
468
490
|
};
|
|
469
491
|
}
|
|
470
492
|
catch (error) {
|
|
471
|
-
logger.error('Failed to set property:', error);
|
|
493
|
+
this.logger.error('Failed to set property:', error);
|
|
472
494
|
throw error;
|
|
473
495
|
}
|
|
474
496
|
}
|
|
@@ -477,7 +499,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
477
499
|
*/
|
|
478
500
|
async listProperties(args) {
|
|
479
501
|
const { pattern, category, is_private, limit = 100, include_values = true } = args;
|
|
480
|
-
logger.info('Listing properties', { pattern, category, limit });
|
|
502
|
+
this.logger.info('Listing properties', { pattern, category, limit });
|
|
481
503
|
try {
|
|
482
504
|
let query = '';
|
|
483
505
|
const conditions = [];
|
|
@@ -535,7 +557,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
535
557
|
};
|
|
536
558
|
}
|
|
537
559
|
catch (error) {
|
|
538
|
-
logger.error('Failed to list properties:', error);
|
|
560
|
+
this.logger.error('Failed to list properties:', error);
|
|
539
561
|
throw error;
|
|
540
562
|
}
|
|
541
563
|
}
|
|
@@ -556,7 +578,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
556
578
|
}]
|
|
557
579
|
};
|
|
558
580
|
}
|
|
559
|
-
logger.info(`Deleting property: ${name}`);
|
|
581
|
+
this.logger.info(`Deleting property: ${name}`);
|
|
560
582
|
try {
|
|
561
583
|
// Find the property
|
|
562
584
|
const response = await this.client.searchRecords('sys_properties', `name=${name}`, 1);
|
|
@@ -585,7 +607,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
585
607
|
};
|
|
586
608
|
}
|
|
587
609
|
catch (error) {
|
|
588
|
-
logger.error('Failed to delete property:', error);
|
|
610
|
+
this.logger.error('Failed to delete property:', error);
|
|
589
611
|
throw error;
|
|
590
612
|
}
|
|
591
613
|
}
|
|
@@ -594,7 +616,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
594
616
|
*/
|
|
595
617
|
async searchProperties(args) {
|
|
596
618
|
const { search_term, search_in = 'all', limit = 50 } = args;
|
|
597
|
-
logger.info(`Searching properties for: ${search_term}`);
|
|
619
|
+
this.logger.info(`Searching properties for: ${search_term}`);
|
|
598
620
|
try {
|
|
599
621
|
let query = '';
|
|
600
622
|
switch (search_in) {
|
|
@@ -642,7 +664,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
642
664
|
};
|
|
643
665
|
}
|
|
644
666
|
catch (error) {
|
|
645
|
-
logger.error('Search failed:', error);
|
|
667
|
+
this.logger.error('Search failed:', error);
|
|
646
668
|
throw error;
|
|
647
669
|
}
|
|
648
670
|
}
|
|
@@ -651,7 +673,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
651
673
|
*/
|
|
652
674
|
async bulkGetProperties(args) {
|
|
653
675
|
const { names, include_metadata = false } = args;
|
|
654
|
-
logger.info(`Bulk getting ${names.length} properties`);
|
|
676
|
+
this.logger.info(`Bulk getting ${names.length} properties`);
|
|
655
677
|
const results = {};
|
|
656
678
|
const errors = [];
|
|
657
679
|
for (const name of names) {
|
|
@@ -673,7 +695,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
673
695
|
}
|
|
674
696
|
}
|
|
675
697
|
catch (error) {
|
|
676
|
-
logger.error(`Failed to get property ${name}:`, error);
|
|
698
|
+
this.logger.error(`Failed to get property ${name}:`, error);
|
|
677
699
|
results[name] = null;
|
|
678
700
|
errors.push(name);
|
|
679
701
|
}
|
|
@@ -702,7 +724,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
702
724
|
*/
|
|
703
725
|
async bulkSetProperties(args) {
|
|
704
726
|
const { properties } = args;
|
|
705
|
-
logger.info(`Bulk setting ${properties.length} properties`);
|
|
727
|
+
this.logger.info(`Bulk setting ${properties.length} properties`);
|
|
706
728
|
const results = {
|
|
707
729
|
created: [],
|
|
708
730
|
updated: [],
|
|
@@ -730,6 +752,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
730
752
|
}
|
|
731
753
|
else {
|
|
732
754
|
// Create
|
|
755
|
+
this.logger.trackAPICall('CREATE', 'sys_properties', 1);
|
|
733
756
|
result = await this.client.createRecord('sys_properties', {
|
|
734
757
|
name: prop.name,
|
|
735
758
|
value: prop.value,
|
|
@@ -747,7 +770,7 @@ ${choices ? `**Choices:** ${choices}` : ''}
|
|
|
747
770
|
this.propertyCache.delete(prop.name);
|
|
748
771
|
}
|
|
749
772
|
catch (error) {
|
|
750
|
-
logger.error(`Failed to set property ${prop.name}:`, error);
|
|
773
|
+
this.logger.error(`Failed to set property ${prop.name}:`, error);
|
|
751
774
|
results.failed.push(`${prop.name}: ${error}`);
|
|
752
775
|
}
|
|
753
776
|
}
|
|
@@ -773,7 +796,7 @@ Total processed: ${properties.length}`
|
|
|
773
796
|
*/
|
|
774
797
|
async exportProperties(args) {
|
|
775
798
|
const { pattern, include_system = false, include_private = false } = args;
|
|
776
|
-
logger.info('Exporting properties', { pattern, include_system, include_private });
|
|
799
|
+
this.logger.info('Exporting properties', { pattern, include_system, include_private });
|
|
777
800
|
try {
|
|
778
801
|
let query = '';
|
|
779
802
|
const conditions = [];
|
|
@@ -823,7 +846,7 @@ ${JSON.stringify(exportData, null, 2)}
|
|
|
823
846
|
};
|
|
824
847
|
}
|
|
825
848
|
catch (error) {
|
|
826
|
-
logger.error('Export failed:', error);
|
|
849
|
+
this.logger.error('Export failed:', error);
|
|
827
850
|
throw error;
|
|
828
851
|
}
|
|
829
852
|
}
|
|
@@ -832,7 +855,7 @@ ${JSON.stringify(exportData, null, 2)}
|
|
|
832
855
|
*/
|
|
833
856
|
async importProperties(args) {
|
|
834
857
|
const { properties, overwrite = false, dry_run = false } = args;
|
|
835
|
-
logger.info('Importing properties', { count: Object.keys(properties).length, overwrite, dry_run });
|
|
858
|
+
this.logger.info('Importing properties', { count: Object.keys(properties).length, overwrite, dry_run });
|
|
836
859
|
const results = {
|
|
837
860
|
would_create: [],
|
|
838
861
|
would_update: [],
|
|
@@ -884,6 +907,7 @@ ${JSON.stringify(exportData, null, 2)}
|
|
|
884
907
|
}
|
|
885
908
|
else {
|
|
886
909
|
// Create
|
|
910
|
+
this.logger.trackAPICall('CREATE', 'sys_properties', 1);
|
|
887
911
|
const result = await this.client.createRecord('sys_properties', {
|
|
888
912
|
name,
|
|
889
913
|
value: propertyData.value,
|
|
@@ -904,7 +928,7 @@ ${JSON.stringify(exportData, null, 2)}
|
|
|
904
928
|
this.propertyCache.delete(name);
|
|
905
929
|
}
|
|
906
930
|
catch (error) {
|
|
907
|
-
logger.error(`Failed to import property ${name}:`, error);
|
|
931
|
+
this.logger.error(`Failed to import property ${name}:`, error);
|
|
908
932
|
results.failed.push(`${name}: ${error}`);
|
|
909
933
|
}
|
|
910
934
|
}
|
|
@@ -946,7 +970,7 @@ Total processed: ${Object.keys(properties).length}`
|
|
|
946
970
|
*/
|
|
947
971
|
async validateProperty(args) {
|
|
948
972
|
const { name, value } = args;
|
|
949
|
-
logger.info(`Validating property: ${name} = ${value}`);
|
|
973
|
+
this.logger.info(`Validating property: ${name} = ${value}`);
|
|
950
974
|
try {
|
|
951
975
|
// Get property metadata
|
|
952
976
|
const response = await this.client.searchRecords('sys_properties', `name=${name}`, 1);
|
|
@@ -1026,7 +1050,7 @@ ${validationResults.join('\n')}
|
|
|
1026
1050
|
};
|
|
1027
1051
|
}
|
|
1028
1052
|
catch (error) {
|
|
1029
|
-
logger.error('Validation failed:', error);
|
|
1053
|
+
this.logger.error('Validation failed:', error);
|
|
1030
1054
|
throw error;
|
|
1031
1055
|
}
|
|
1032
1056
|
}
|
|
@@ -1035,7 +1059,7 @@ ${validationResults.join('\n')}
|
|
|
1035
1059
|
*/
|
|
1036
1060
|
async getCategories(args) {
|
|
1037
1061
|
const { include_counts = true } = args;
|
|
1038
|
-
logger.info('Getting property categories');
|
|
1062
|
+
this.logger.info('Getting property categories');
|
|
1039
1063
|
try {
|
|
1040
1064
|
// Get distinct suffixes (categories)
|
|
1041
1065
|
const response = await this.client.searchRecords('sys_properties', '', 1000);
|
|
@@ -1067,7 +1091,7 @@ ${validationResults.join('\n')}
|
|
|
1067
1091
|
};
|
|
1068
1092
|
}
|
|
1069
1093
|
catch (error) {
|
|
1070
|
-
logger.error('Failed to get categories:', error);
|
|
1094
|
+
this.logger.error('Failed to get categories:', error);
|
|
1071
1095
|
throw error;
|
|
1072
1096
|
}
|
|
1073
1097
|
}
|
|
@@ -1076,7 +1100,7 @@ ${validationResults.join('\n')}
|
|
|
1076
1100
|
*/
|
|
1077
1101
|
async getPropertyHistory(args) {
|
|
1078
1102
|
const { name, limit = 10 } = args;
|
|
1079
|
-
logger.info(`Getting history for property: ${name}`);
|
|
1103
|
+
this.logger.info(`Getting history for property: ${name}`);
|
|
1080
1104
|
try {
|
|
1081
1105
|
// First, get the property to get its sys_id
|
|
1082
1106
|
const propResponse = await this.client.searchRecords('sys_properties', `name=${name}`, 1);
|
|
@@ -1116,7 +1140,7 @@ ${validationResults.join('\n')}
|
|
|
1116
1140
|
};
|
|
1117
1141
|
}
|
|
1118
1142
|
catch (error) {
|
|
1119
|
-
logger.error('Failed to get history:', error);
|
|
1143
|
+
this.logger.error('Failed to get history:', error);
|
|
1120
1144
|
// Audit might not be available
|
|
1121
1145
|
return {
|
|
1122
1146
|
content: [{
|
|
@@ -1131,7 +1155,7 @@ Note: Audit history requires sys_audit to be enabled for sys_properties table.`
|
|
|
1131
1155
|
async start() {
|
|
1132
1156
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
1133
1157
|
await this.server.connect(transport);
|
|
1134
|
-
logger.info('ServiceNow System Properties MCP Server started');
|
|
1158
|
+
this.logger.info('ServiceNow System Properties MCP Server started');
|
|
1135
1159
|
}
|
|
1136
1160
|
}
|
|
1137
1161
|
exports.ServiceNowSystemPropertiesMCP = ServiceNowSystemPropertiesMCP;
|
|
@@ -10,7 +10,7 @@ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
|
10
10
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
11
11
|
const servicenow_client_js_1 = require("../utils/servicenow-client.js");
|
|
12
12
|
const snow_oauth_js_1 = require("../utils/snow-oauth.js");
|
|
13
|
-
const
|
|
13
|
+
const mcp_logger_js_1 = require("../shared/mcp-logger.js");
|
|
14
14
|
const fs_1 = require("fs");
|
|
15
15
|
const path_1 = require("path");
|
|
16
16
|
class ServiceNowUpdateSetMCP {
|
|
@@ -26,7 +26,7 @@ class ServiceNowUpdateSetMCP {
|
|
|
26
26
|
});
|
|
27
27
|
this.client = new servicenow_client_js_1.ServiceNowClient();
|
|
28
28
|
this.oauth = new snow_oauth_js_1.ServiceNowOAuth();
|
|
29
|
-
this.logger = new
|
|
29
|
+
this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowUpdateSetMCP');
|
|
30
30
|
this.sessionsPath = (0, path_1.join)(process.cwd(), 'memory', 'update-set-sessions');
|
|
31
31
|
// Debug: Test credentials on startup
|
|
32
32
|
this.testCredentials();
|
|
@@ -227,33 +227,48 @@ class ServiceNowUpdateSetMCP {
|
|
|
227
227
|
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
228
228
|
const { name, arguments: args } = request.params;
|
|
229
229
|
try {
|
|
230
|
+
// Start operation with token tracking
|
|
231
|
+
this.logger.operationStart(name, args);
|
|
230
232
|
// Check authentication for all operations
|
|
231
233
|
const isAuthenticated = await this.oauth.isAuthenticated();
|
|
232
234
|
if (!isAuthenticated) {
|
|
233
235
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, 'Not authenticated. Run "snow-flow auth login" first.');
|
|
234
236
|
}
|
|
237
|
+
let result;
|
|
235
238
|
switch (name) {
|
|
236
239
|
case 'snow_update_set_create':
|
|
237
|
-
|
|
240
|
+
result = await this.createUpdateSet(args);
|
|
241
|
+
break;
|
|
238
242
|
case 'snow_update_set_switch':
|
|
239
|
-
|
|
243
|
+
result = await this.switchUpdateSet(args);
|
|
244
|
+
break;
|
|
240
245
|
case 'snow_update_set_current':
|
|
241
|
-
|
|
246
|
+
result = await this.getCurrentUpdateSet();
|
|
247
|
+
break;
|
|
242
248
|
case 'snow_update_set_list':
|
|
243
|
-
|
|
249
|
+
result = await this.listUpdateSets(args);
|
|
250
|
+
break;
|
|
244
251
|
case 'snow_update_set_complete':
|
|
245
|
-
|
|
252
|
+
result = await this.completeUpdateSet(args);
|
|
253
|
+
break;
|
|
246
254
|
case 'snow_update_set_add_artifact':
|
|
247
|
-
|
|
255
|
+
result = await this.addArtifactToSession(args);
|
|
256
|
+
break;
|
|
248
257
|
case 'snow_update_set_preview':
|
|
249
|
-
|
|
258
|
+
result = await this.previewUpdateSet(args);
|
|
259
|
+
break;
|
|
250
260
|
case 'snow_update_set_export':
|
|
251
|
-
|
|
261
|
+
result = await this.exportUpdateSet(args);
|
|
262
|
+
break;
|
|
252
263
|
case 'snow_ensure_active_update_set':
|
|
253
|
-
|
|
264
|
+
result = await this.ensureActiveUpdateSet(args);
|
|
265
|
+
break;
|
|
254
266
|
default:
|
|
255
267
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
256
268
|
}
|
|
269
|
+
// Complete operation with token tracking
|
|
270
|
+
this.logger.operationComplete(name, result);
|
|
271
|
+
return result;
|
|
257
272
|
}
|
|
258
273
|
catch (error) {
|
|
259
274
|
if (error instanceof types_js_1.McpError)
|
|
@@ -267,6 +282,7 @@ class ServiceNowUpdateSetMCP {
|
|
|
267
282
|
try {
|
|
268
283
|
this.logger.info('Creating new Update Set', args);
|
|
269
284
|
// Create Update Set in ServiceNow
|
|
285
|
+
this.logger.trackAPICall('CREATE', 'sys_update_set', 1);
|
|
270
286
|
const response = await this.client.createUpdateSet({
|
|
271
287
|
name: args.name,
|
|
272
288
|
description: args.description,
|
|
@@ -284,6 +300,7 @@ class ServiceNowUpdateSetMCP {
|
|
|
284
300
|
const autoSwitch = args.auto_switch !== false;
|
|
285
301
|
let switchedToUpdateSet = false;
|
|
286
302
|
if (autoSwitch) {
|
|
303
|
+
this.logger.trackAPICall('UPDATE', 'sys_update_set', 1);
|
|
287
304
|
await this.client.setCurrentUpdateSet(response.data.sys_id);
|
|
288
305
|
switchedToUpdateSet = true;
|
|
289
306
|
// Create local session
|
|
@@ -339,6 +356,7 @@ Use \`snow_update_set_switch\` to activate this Update Set before making changes
|
|
|
339
356
|
try {
|
|
340
357
|
this.logger.info('Switching to Update Set', { update_set_id: args.update_set_id });
|
|
341
358
|
// Set as current in ServiceNow
|
|
359
|
+
this.logger.trackAPICall('UPDATE', 'sys_update_set', 1);
|
|
342
360
|
await this.client.setCurrentUpdateSet(args.update_set_id);
|
|
343
361
|
// Load or create session
|
|
344
362
|
const sessionFile = (0, path_1.join)(this.sessionsPath, `${args.update_set_id}.json`);
|
|
@@ -348,6 +366,7 @@ Use \`snow_update_set_switch\` to activate this Update Set before making changes
|
|
|
348
366
|
}
|
|
349
367
|
catch {
|
|
350
368
|
// Create new session for existing Update Set
|
|
369
|
+
this.logger.trackAPICall('GET', 'sys_update_set', 1);
|
|
351
370
|
const updateSet = await this.client.getUpdateSet(args.update_set_id);
|
|
352
371
|
this.currentSession = {
|
|
353
372
|
update_set_id: args.update_set_id,
|
|
@@ -382,6 +401,7 @@ All subsequent changes will be tracked in this Update Set.`
|
|
|
382
401
|
async getCurrentUpdateSet() {
|
|
383
402
|
if (!this.currentSession) {
|
|
384
403
|
// Try to get from ServiceNow
|
|
404
|
+
this.logger.trackAPICall('GET', 'sys_update_set', 1);
|
|
385
405
|
const current = await this.client.getCurrentUpdateSet();
|
|
386
406
|
if (current.success && current.data) {
|
|
387
407
|
return {
|
|
@@ -423,6 +443,7 @@ ${this.currentSession.artifacts.length > 0
|
|
|
423
443
|
}
|
|
424
444
|
async listUpdateSets(args) {
|
|
425
445
|
try {
|
|
446
|
+
this.logger.trackAPICall('SEARCH', 'sys_update_set', args.limit || 10);
|
|
426
447
|
const response = await this.client.listUpdateSets({
|
|
427
448
|
state: args.state,
|
|
428
449
|
limit: args.limit || 10
|
|
@@ -462,6 +483,7 @@ ${updateSets.map((us) => `
|
|
|
462
483
|
throw new Error('No Update Set specified and no active session');
|
|
463
484
|
}
|
|
464
485
|
// Mark as complete in ServiceNow
|
|
486
|
+
this.logger.trackAPICall('UPDATE', 'sys_update_set', 1);
|
|
465
487
|
const response = await this.client.completeUpdateSet(updateSetId, args.notes);
|
|
466
488
|
if (!response.success) {
|
|
467
489
|
throw new Error(response.error || 'Failed to complete Update Set');
|
|
@@ -559,6 +581,7 @@ ${autoCreatedNotice}
|
|
|
559
581
|
throw new Error('No Update Set specified and no active session');
|
|
560
582
|
}
|
|
561
583
|
// Get Update Set details and changes
|
|
584
|
+
this.logger.trackAPICall('GET', 'sys_update_set_preview', 1);
|
|
562
585
|
const response = await this.client.previewUpdateSet(updateSetId);
|
|
563
586
|
if (!response.success) {
|
|
564
587
|
throw new Error(response.error || 'Failed to preview Update Set');
|
|
@@ -601,6 +624,7 @@ ${changes.length > 20 ? `\n... and ${changes.length - 20} more changes` : ''}
|
|
|
601
624
|
throw new Error('Update Set ID is required for export');
|
|
602
625
|
}
|
|
603
626
|
// Export Update Set as XML
|
|
627
|
+
this.logger.trackAPICall('GET', 'sys_update_set_export', 1);
|
|
604
628
|
const response = await this.client.exportUpdateSet(updateSetId);
|
|
605
629
|
if (!response.success) {
|
|
606
630
|
throw new Error(response.error || 'Failed to export Update Set');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.14",
|
|
4
4
|
"description": "ServiceNow development framework with MCP server integration. Executes background scripts using ES5 JavaScript only (ServiceNow Rhino engine requirement). Provides 12 MCP servers for ServiceNow operations including widget deployment with coherence validation, table operations, script execution, and system property management.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|