snow-flow 3.4.13 → 3.4.15

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.
@@ -12,7 +12,7 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
12
12
  const servicenow_client_js_1 = require("../utils/servicenow-client.js");
13
13
  const mcp_auth_middleware_js_1 = require("../utils/mcp-auth-middleware.js");
14
14
  const mcp_config_manager_js_1 = require("../utils/mcp-config-manager.js");
15
- const logger_js_1 = require("../utils/logger.js");
15
+ const mcp_logger_js_1 = require("../shared/mcp-logger.js");
16
16
  class ServiceNowIntegrationMCP {
17
17
  constructor() {
18
18
  this.server = new index_js_1.Server({
@@ -24,7 +24,7 @@ class ServiceNowIntegrationMCP {
24
24
  },
25
25
  });
26
26
  this.client = new servicenow_client_js_1.ServiceNowClient();
27
- this.logger = new logger_js_1.Logger('ServiceNowIntegrationMCP');
27
+ this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowIntegrationMCP');
28
28
  this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
29
29
  this.setupHandlers();
30
30
  }
@@ -177,34 +177,50 @@ class ServiceNowIntegrationMCP {
177
177
  this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
178
178
  try {
179
179
  const { name, arguments: args } = request.params;
180
+ // Start operation with token tracking
181
+ this.logger.operationStart(name, args);
180
182
  const authResult = await mcp_auth_middleware_js_1.mcpAuth.ensureAuthenticated();
181
183
  if (!authResult.success) {
182
184
  throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, authResult.error || 'Authentication required');
183
185
  }
186
+ let result;
184
187
  switch (name) {
185
188
  case 'snow_create_rest_message':
186
- return await this.createRestMessage(args);
189
+ result = await this.createRestMessage(args);
190
+ break;
187
191
  case 'snow_create_rest_method':
188
- return await this.createRestMethod(args);
192
+ result = await this.createRestMethod(args);
193
+ break;
189
194
  case 'snow_create_transform_map':
190
- return await this.createTransformMap(args);
195
+ result = await this.createTransformMap(args);
196
+ break;
191
197
  case 'snow_create_field_map':
192
- return await this.createFieldMap(args);
198
+ result = await this.createFieldMap(args);
199
+ break;
193
200
  case 'snow_create_import_set':
194
- return await this.createImportSet(args);
201
+ result = await this.createImportSet(args);
202
+ break;
195
203
  case 'snow_create_web_service':
196
- return await this.createWebService(args);
204
+ result = await this.createWebService(args);
205
+ break;
197
206
  case 'snow_create_email_config':
198
- return await this.createEmailConfig(args);
207
+ result = await this.createEmailConfig(args);
208
+ break;
199
209
  case 'snow_discover_integration_endpoints':
200
- return await this.discoverIntegrationEndpoints(args);
210
+ result = await this.discoverIntegrationEndpoints(args);
211
+ break;
201
212
  case 'snow_test_integration':
202
- return await this.testIntegration(args);
213
+ result = await this.testIntegration(args);
214
+ break;
203
215
  case 'snow_discover_data_sources':
204
- return await this.discoverDataSources(args);
216
+ result = await this.discoverDataSources(args);
217
+ break;
205
218
  default:
206
219
  throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
207
220
  }
221
+ // Complete operation with token tracking
222
+ this.logger.operationComplete(name, result);
223
+ return result;
208
224
  }
209
225
  catch (error) {
210
226
  this.logger.error(`Error in ${request.params.name}:`, error);
@@ -228,6 +244,7 @@ class ServiceNowIntegrationMCP {
228
244
  authentication_profile: args.authProfile || ''
229
245
  };
230
246
  const updateSetResult = await this.client.ensureUpdateSet();
247
+ this.logger.trackAPICall('CREATE', 'sys_rest_message', 1);
231
248
  const response = await this.client.createRecord('sys_rest_message', restMessageData);
232
249
  if (!response.success) {
233
250
  throw new Error(`Failed to create REST Message: ${response.error}`);
@@ -263,6 +280,7 @@ class ServiceNowIntegrationMCP {
263
280
  content: args.content || '',
264
281
  headers: JSON.stringify(args.headers || {})
265
282
  };
283
+ this.logger.trackAPICall('CREATE', 'sys_rest_message_fn', 1);
266
284
  const response = await this.client.createRecord('sys_rest_message_fn', restMethodData);
267
285
  if (!response.success) {
268
286
  throw new Error(`Failed to create REST Method: ${response.error}`);
@@ -303,6 +321,7 @@ class ServiceNowIntegrationMCP {
303
321
  active: args.active !== false
304
322
  };
305
323
  const updateSetResult = await this.client.ensureUpdateSet();
324
+ this.logger.trackAPICall('CREATE', 'sys_transform_map', 1);
306
325
  const response = await this.client.createRecord('sys_transform_map', transformMapData);
307
326
  if (!response.success) {
308
327
  throw new Error(`Failed to create Transform Map: ${response.error}`);
@@ -341,6 +360,7 @@ class ServiceNowIntegrationMCP {
341
360
  default_value: args.defaultValue || '',
342
361
  map: transformMap.sys_id
343
362
  };
363
+ this.logger.trackAPICall('CREATE', 'sys_transform_entry', 1);
344
364
  const response = await this.client.createRecord('sys_transform_entry', fieldMapData);
345
365
  if (!response.success) {
346
366
  throw new Error(`Failed to create Field Map: ${response.error}`);
@@ -379,6 +399,7 @@ class ServiceNowIntegrationMCP {
379
399
  };
380
400
  const updateSetResult = await this.client.ensureUpdateSet();
381
401
  // Create the import set table structure first
402
+ this.logger.trackAPICall('CREATE', 'sys_db_object', 1);
382
403
  const response = await this.client.createRecord('sys_db_object', importSetData);
383
404
  if (!response.success) {
384
405
  this.logger.error('Import Set creation failed with response:', response);
@@ -393,6 +414,7 @@ class ServiceNowIntegrationMCP {
393
414
  description: 'Row number from import file'
394
415
  };
395
416
  try {
417
+ this.logger.trackAPICall('CREATE', 'sys_dictionary', 1);
396
418
  await this.client.createRecord('sys_dictionary', fieldData);
397
419
  }
398
420
  catch (fieldError) {
@@ -426,6 +448,7 @@ class ServiceNowIntegrationMCP {
426
448
  namespace: args.namespace || ''
427
449
  };
428
450
  const updateSetResult = await this.client.ensureUpdateSet();
451
+ this.logger.trackAPICall('CREATE', 'sys_web_service', 1);
429
452
  const response = await this.client.createRecord('sys_web_service', webServiceData);
430
453
  if (!response.success) {
431
454
  throw new Error(`Failed to create Web Service: ${response.error}`);
@@ -458,6 +481,7 @@ class ServiceNowIntegrationMCP {
458
481
  description: args.description || ''
459
482
  };
460
483
  const updateSetResult = await this.client.ensureUpdateSet();
484
+ this.logger.trackAPICall('CREATE', 'sys_email_account', 1);
461
485
  const response = await this.client.createRecord('sys_email_account', emailConfigData);
462
486
  if (!response.success) {
463
487
  throw new Error(`Failed to create Email Configuration: ${response.error}`);
@@ -484,6 +508,7 @@ class ServiceNowIntegrationMCP {
484
508
  const endpoints = [];
485
509
  // Discover REST Messages
486
510
  if (type === 'all' || type === 'REST') {
511
+ this.logger.trackAPICall('SEARCH', 'sys_rest_message', 50);
487
512
  const restMessages = await this.client.searchRecords('sys_rest_message', '', 50);
488
513
  if (restMessages.success) {
489
514
  endpoints.push({
@@ -499,6 +524,7 @@ class ServiceNowIntegrationMCP {
499
524
  }
500
525
  // Discover Web Services
501
526
  if (type === 'all' || type === 'SOAP') {
527
+ this.logger.trackAPICall('SEARCH', 'sys_web_service', 50);
502
528
  const webServices = await this.client.searchRecords('sys_web_service', '', 50);
503
529
  if (webServices.success) {
504
530
  endpoints.push({
@@ -514,6 +540,7 @@ class ServiceNowIntegrationMCP {
514
540
  }
515
541
  // Discover Email Accounts
516
542
  if (type === 'all' || type === 'EMAIL') {
543
+ this.logger.trackAPICall('SEARCH', 'sys_email_account', 50);
517
544
  const emailAccounts = await this.client.searchRecords('sys_email_account', '', 50);
518
545
  if (emailAccounts.success) {
519
546
  endpoints.push({
@@ -552,6 +579,7 @@ class ServiceNowIntegrationMCP {
552
579
  throw new Error(`Integration endpoint not found: ${args.endpointName}`);
553
580
  }
554
581
  // Get available test methods
582
+ this.logger.trackAPICall('SEARCH', 'sys_rest_message_fn', 10);
555
583
  const methods = await this.client.searchRecords('sys_rest_message_fn', `rest_message=${restMessage.sys_id}`, 10);
556
584
  if (!methods.success || !methods.data.result.length) {
557
585
  throw new Error(`No methods found for REST Message: ${args.endpointName}`);
@@ -576,6 +604,7 @@ class ServiceNowIntegrationMCP {
576
604
  this.logger.info('Discovering data sources...');
577
605
  const dataSources = [];
578
606
  // Discover Import Sets
607
+ this.logger.trackAPICall('SEARCH', 'sys_import_set_table', 50);
579
608
  const importSets = await this.client.searchRecords('sys_import_set_table', '', 50);
580
609
  if (importSets.success) {
581
610
  dataSources.push({
@@ -589,6 +618,7 @@ class ServiceNowIntegrationMCP {
589
618
  });
590
619
  }
591
620
  // Discover Transform Maps
621
+ this.logger.trackAPICall('SEARCH', 'sys_transform_map', 50);
592
622
  const transformMaps = await this.client.searchRecords('sys_transform_map', '', 50);
593
623
  if (transformMaps.success) {
594
624
  dataSources.push({
@@ -602,6 +632,7 @@ class ServiceNowIntegrationMCP {
602
632
  });
603
633
  }
604
634
  // Discover Data Sources
635
+ this.logger.trackAPICall('SEARCH', 'sys_data_source', 50);
605
636
  const dataSourcesResponse = await this.client.searchRecords('sys_data_source', '', 50);
606
637
  if (dataSourcesResponse.success) {
607
638
  dataSources.push({
@@ -630,6 +661,7 @@ class ServiceNowIntegrationMCP {
630
661
  async getAuthenticationTypes() {
631
662
  // Discover available authentication types dynamically
632
663
  try {
664
+ this.logger.trackAPICall('SEARCH', 'sys_choice', 10);
633
665
  const authTypes = await this.client.searchRecords('sys_choice', 'name=sys_rest_message^element=authentication_type', 10);
634
666
  if (authTypes.success) {
635
667
  return authTypes.data.result.map((choice) => choice.value);
@@ -642,6 +674,7 @@ class ServiceNowIntegrationMCP {
642
674
  }
643
675
  async getTableInfo(tableName) {
644
676
  try {
677
+ this.logger.trackAPICall('SEARCH', 'sys_db_object', 1);
645
678
  const tableResponse = await this.client.searchRecords('sys_db_object', `name=${tableName}`, 1);
646
679
  if (tableResponse.success && tableResponse.data?.result?.length > 0) {
647
680
  const table = tableResponse.data.result[0];
@@ -656,6 +689,7 @@ class ServiceNowIntegrationMCP {
656
689
  }
657
690
  async getTableFields(tableName) {
658
691
  try {
692
+ this.logger.trackAPICall('SEARCH', 'sys_dictionary', 100);
659
693
  const fieldsResponse = await this.client.searchRecords('sys_dictionary', `nameSTARTSWITH${tableName}^element!=NULL`, 100);
660
694
  if (fieldsResponse.success) {
661
695
  return fieldsResponse.data.result.map((field) => field.element);
@@ -669,6 +703,7 @@ class ServiceNowIntegrationMCP {
669
703
  }
670
704
  async findRestMessage(name) {
671
705
  try {
706
+ this.logger.trackAPICall('SEARCH', 'sys_rest_message', 1);
672
707
  const response = await this.client.searchRecords('sys_rest_message', `name=${name}`, 1);
673
708
  if (response.success && response.data?.result?.length > 0) {
674
709
  return response.data.result[0];
@@ -682,6 +717,7 @@ class ServiceNowIntegrationMCP {
682
717
  }
683
718
  async findTransformMap(name) {
684
719
  try {
720
+ this.logger.trackAPICall('SEARCH', 'sys_transform_map', 1);
685
721
  const response = await this.client.searchRecords('sys_transform_map', `name=${name}`, 1);
686
722
  if (response.success && response.data?.result?.length > 0) {
687
723
  return response.data.result[0];
@@ -12,7 +12,7 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
12
12
  const servicenow_client_js_1 = require("../utils/servicenow-client.js");
13
13
  const mcp_auth_middleware_js_1 = require("../utils/mcp-auth-middleware.js");
14
14
  const mcp_config_manager_js_1 = require("../utils/mcp-config-manager.js");
15
- const logger_js_1 = require("../utils/logger.js");
15
+ const mcp_logger_js_1 = require("../shared/mcp-logger.js");
16
16
  class ServiceNowKnowledgeCatalogMCP {
17
17
  constructor() {
18
18
  this.server = new index_js_1.Server({
@@ -24,7 +24,7 @@ class ServiceNowKnowledgeCatalogMCP {
24
24
  },
25
25
  });
26
26
  this.client = new servicenow_client_js_1.ServiceNowClient();
27
- this.logger = new logger_js_1.Logger('ServiceNowKnowledgeCatalogMCP');
27
+ this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowKnowledgeCatalogMCP');
28
28
  this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
29
29
  this.setupHandlers();
30
30
  }
@@ -263,44 +263,64 @@ class ServiceNowKnowledgeCatalogMCP {
263
263
  this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
264
264
  try {
265
265
  const { name, arguments: args } = request.params;
266
+ // Start operation with token tracking
267
+ this.logger.operationStart(name, args);
266
268
  const authResult = await mcp_auth_middleware_js_1.mcpAuth.ensureAuthenticated();
267
269
  if (!authResult.success) {
268
270
  throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, authResult.error || 'Authentication required');
269
271
  }
272
+ let result;
270
273
  switch (name) {
271
274
  // Knowledge Management
272
275
  case 'snow_create_knowledge_article':
273
- return await this.createKnowledgeArticle(args);
276
+ result = await this.createKnowledgeArticle(args);
277
+ break;
274
278
  case 'snow_search_knowledge':
275
- return await this.searchKnowledge(args);
279
+ result = await this.searchKnowledge(args);
280
+ break;
276
281
  case 'snow_update_knowledge_article':
277
- return await this.updateKnowledgeArticle(args);
282
+ result = await this.updateKnowledgeArticle(args);
283
+ break;
278
284
  case 'snow_retire_knowledge_article':
279
- return await this.retireKnowledgeArticle(args);
285
+ result = await this.retireKnowledgeArticle(args);
286
+ break;
280
287
  case 'snow_create_knowledge_base':
281
- return await this.createKnowledgeBase(args);
288
+ result = await this.createKnowledgeBase(args);
289
+ break;
282
290
  case 'snow_discover_knowledge_bases':
283
- return await this.discoverKnowledgeBases(args);
291
+ result = await this.discoverKnowledgeBases(args);
292
+ break;
284
293
  // Service Catalog
285
294
  case 'snow_create_catalog_item':
286
- return await this.createCatalogItem(args);
295
+ result = await this.createCatalogItem(args);
296
+ break;
287
297
  case 'snow_create_catalog_variable':
288
- return await this.createCatalogVariable(args);
298
+ result = await this.createCatalogVariable(args);
299
+ break;
289
300
  case 'snow_create_catalog_ui_policy':
290
- return await this.createCatalogUIPolicy(args);
301
+ result = await this.createCatalogUIPolicy(args);
302
+ break;
291
303
  case 'snow_create_catalog_client_script':
292
- return await this.createCatalogClientScript(args);
304
+ result = await this.createCatalogClientScript(args);
305
+ break;
293
306
  case 'snow_search_catalog':
294
- return await this.searchCatalog(args);
307
+ result = await this.searchCatalog(args);
308
+ break;
295
309
  case 'snow_order_catalog_item':
296
- return await this.orderCatalogItem(args);
310
+ result = await this.orderCatalogItem(args);
311
+ break;
297
312
  case 'snow_get_catalog_item_details':
298
- return await this.getCatalogItemDetails(args);
313
+ result = await this.getCatalogItemDetails(args);
314
+ break;
299
315
  case 'snow_discover_catalogs':
300
- return await this.discoverCatalogs(args);
316
+ result = await this.discoverCatalogs(args);
317
+ break;
301
318
  default:
302
319
  throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
303
320
  }
321
+ // Complete operation with token tracking
322
+ this.logger.operationComplete(name, result);
323
+ return result;
304
324
  }
305
325
  catch (error) {
306
326
  this.logger.error(`Error in ${request.params.name}:`, error);
@@ -344,6 +364,7 @@ class ServiceNowKnowledgeCatalogMCP {
344
364
  author: args.author || ''
345
365
  };
346
366
  const updateSetResult = await this.client.ensureUpdateSet();
367
+ this.logger.trackAPICall('CREATE', 'kb_knowledge', 1);
347
368
  const response = await this.client.createRecord('kb_knowledge', articleData);
348
369
  if (!response.success) {
349
370
  throw new Error(`Failed to create knowledge article: ${response.error}`);
@@ -392,6 +413,7 @@ ${args.valid_to ? `📅 Valid Until: ${args.valid_to}` : ''}
392
413
  query += '^workflow_state=published'; // Default to published only
393
414
  }
394
415
  const limit = args.limit || 10;
416
+ this.logger.trackAPICall('SEARCH', 'kb_knowledge', limit);
395
417
  const response = await this.client.searchRecords('kb_knowledge', query, limit);
396
418
  if (!response.success) {
397
419
  throw new Error('Failed to search knowledge articles');
@@ -450,6 +472,7 @@ ${articleList}
450
472
  updateData.meta_description = args.meta_description;
451
473
  if (args.keywords)
452
474
  updateData.keywords = args.keywords.join(',');
475
+ this.logger.trackAPICall('UPDATE', 'kb_knowledge', 1);
453
476
  const response = await this.client.updateRecord('kb_knowledge', args.sys_id, updateData);
454
477
  if (!response.success) {
455
478
  throw new Error(`Failed to update knowledge article: ${response.error}`);
@@ -487,6 +510,7 @@ ${args.valid_to ? `📅 Valid Until: ${args.valid_to}` : ''}
487
510
  if (args.replacement_article) {
488
511
  updateData['replacement_article'] = args.replacement_article;
489
512
  }
513
+ this.logger.trackAPICall('UPDATE', 'kb_knowledge', 1);
490
514
  const response = await this.client.updateRecord('kb_knowledge', args.sys_id, updateData);
491
515
  if (!response.success) {
492
516
  throw new Error(`Failed to retire knowledge article: ${response.error}`);
@@ -633,6 +657,7 @@ ${kbText}
633
657
  mobile_hide_price: args.mobile_hide_price || false
634
658
  };
635
659
  const updateSetResult = await this.client.ensureUpdateSet();
660
+ this.logger.trackAPICall('CREATE', 'sc_cat_item', 1);
636
661
  const response = await this.client.createRecord('sc_cat_item', itemData);
637
662
  if (!response.success) {
638
663
  throw new Error(`Failed to create catalog item: ${response.error}`);
@@ -808,6 +833,7 @@ ${args.variable ? `📝 Variable: ${args.variable}` : ''}
808
833
  query += 'active=true';
809
834
  }
810
835
  const limit = args.limit || 20;
836
+ this.logger.trackAPICall('SEARCH', 'sc_cat_item', limit);
811
837
  const response = await this.client.searchRecords('sc_cat_item', query, limit);
812
838
  if (!response.success) {
813
839
  throw new Error('Failed to search catalog');
@@ -73,7 +73,7 @@ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
73
73
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
74
74
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
75
75
  const tf = __importStar(require("@tensorflow/tfjs-node"));
76
- const logger_js_1 = require("../utils/logger.js");
76
+ const mcp_logger_js_1 = require("./shared/mcp-logger.js");
77
77
  const servicenow_client_js_1 = require("../utils/servicenow-client.js");
78
78
  const ml_data_fetcher_js_1 = require("../utils/ml-data-fetcher.js");
79
79
  class ServiceNowMachineLearningMCP {
@@ -85,7 +85,7 @@ class ServiceNowMachineLearningMCP {
85
85
  this.hasPA = false;
86
86
  this.hasPI = false;
87
87
  this.mlAPICheckComplete = false;
88
- this.logger = new logger_js_1.Logger('ServiceNowMachineLearning');
88
+ this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowMachineLearning');
89
89
  this.client = new servicenow_client_js_1.ServiceNowClient();
90
90
  this.server = new index_js_1.Server({
91
91
  name: 'servicenow-machine-learning',
@@ -484,46 +484,68 @@ class ServiceNowMachineLearningMCP {
484
484
  this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
485
485
  const { name, arguments: args } = request.params;
486
486
  try {
487
+ // Start operation with token tracking
488
+ this.logger.operationStart(name, args);
489
+ let result;
487
490
  switch (name) {
488
491
  // Training
489
492
  case 'ml_train_incident_classifier':
490
- return await this.trainIncidentClassifier(args);
493
+ result = await this.trainIncidentClassifier(args);
494
+ break;
491
495
  case 'ml_train_change_risk':
492
- return await this.trainChangeRiskModel(args);
496
+ result = await this.trainChangeRiskModel(args);
497
+ break;
493
498
  case 'ml_train_anomaly_detector':
494
- return await this.trainAnomalyDetector(args);
499
+ result = await this.trainAnomalyDetector(args);
500
+ break;
495
501
  // Prediction
496
502
  case 'ml_classify_incident':
497
- return await this.classifyIncident(args);
503
+ result = await this.classifyIncident(args);
504
+ break;
498
505
  case 'ml_predict_change_risk':
499
- return await this.predictChangeRisk(args);
506
+ result = await this.predictChangeRisk(args);
507
+ break;
500
508
  case 'ml_forecast_incidents':
501
- return await this.forecastIncidents(args);
509
+ result = await this.forecastIncidents(args);
510
+ break;
502
511
  case 'ml_detect_anomalies':
503
- return await this.detectAnomalies(args);
512
+ result = await this.detectAnomalies(args);
513
+ break;
504
514
  // Management
505
515
  case 'ml_model_status':
506
- return await this.getModelStatus(args);
516
+ result = await this.getModelStatus(args);
517
+ break;
507
518
  case 'ml_evaluate_model':
508
- return await this.evaluateModel(args);
519
+ result = await this.evaluateModel(args);
520
+ break;
509
521
  // ServiceNow Native ML
510
522
  case 'ml_performance_analytics':
511
- return await this.performanceAnalytics(args);
523
+ result = await this.performanceAnalytics(args);
524
+ break;
512
525
  case 'ml_predictive_intelligence':
513
- return await this.predictiveIntelligence(args);
526
+ result = await this.predictiveIntelligence(args);
527
+ break;
514
528
  case 'ml_agent_intelligence':
515
- return await this.agentIntelligence(args);
529
+ result = await this.agentIntelligence(args);
530
+ break;
516
531
  case 'ml_process_optimization':
517
- return await this.processOptimization(args);
532
+ result = await this.processOptimization(args);
533
+ break;
518
534
  case 'ml_virtual_agent_nlu':
519
- return await this.virtualAgentNLU(args);
535
+ result = await this.virtualAgentNLU(args);
536
+ break;
520
537
  case 'ml_hybrid_recommendation':
521
- return await this.hybridRecommendation(args);
538
+ result = await this.hybridRecommendation(args);
539
+ break;
522
540
  default:
523
541
  throw new Error(`Unknown tool: ${name}`);
524
542
  }
543
+ // Complete operation with token tracking
544
+ this.logger.operationComplete(name, result);
545
+ return result;
525
546
  }
526
547
  catch (error) {
548
+ this.logger.error(`ML tool execution failed: ${name}`, error);
527
549
  return {
528
550
  content: [{
529
551
  type: 'text',
@@ -589,6 +611,7 @@ class ServiceNowMachineLearningMCP {
589
611
  }
590
612
  catch (aggError) {
591
613
  // Final fallback: Estimate based on a sample
614
+ this.logger.trackAPICall('SEARCH', 'incident', 1000);
592
615
  const sampleResult = await this.client.searchRecords('incident', countQuery, 1000);
593
616
  if (sampleResult.success && sampleResult.data?.result) {
594
617
  totalAvailable = sampleResult.data.result.length >= 1000 ? 5000 : sampleResult.data.result.length;
@@ -1784,6 +1807,7 @@ class ServiceNowMachineLearningMCP {
1784
1807
  if (toolName === 'snow_query_table') {
1785
1808
  const { table, query: q, limit: l, fields, include_content } = args;
1786
1809
  // Use the client to fetch data
1810
+ this.logger.trackAPICall('SEARCH', table, l || 100);
1787
1811
  const response = await this.client.searchRecords(table, q || '', l || 100);
1788
1812
  if (!response.success) {
1789
1813
  throw new Error(`Query failed: ${response.error}`);
@@ -2018,6 +2042,7 @@ class ServiceNowMachineLearningMCP {
2018
2042
  if (toolName === 'snow_query_table') {
2019
2043
  const { table, query: q, limit: l, fields, include_content } = args;
2020
2044
  // Use the client to fetch data
2045
+ this.logger.trackAPICall('SEARCH', table, l || 100);
2021
2046
  const response = await this.client.searchRecords(table, q || '', l || 100);
2022
2047
  if (!response.success) {
2023
2048
  throw new Error(`Query failed: ${response.error}`);
@@ -3002,6 +3027,7 @@ class ServiceNowMachineLearningMCP {
3002
3027
  const tableName = tableMatch[1];
3003
3028
  const query = params.sysparm_query || '';
3004
3029
  const limit = params.sysparm_limit || 100;
3030
+ this.logger.trackAPICall('SEARCH', tableName, limit);
3005
3031
  const response = await this.client.searchRecords(tableName, query, limit);
3006
3032
  if (response.success) {
3007
3033
  return {
@@ -3018,6 +3044,7 @@ class ServiceNowMachineLearningMCP {
3018
3044
  const tableName = statsMatch[1];
3019
3045
  const query = params.sysparm_query || '';
3020
3046
  // Use a limit of 1 with count to get total
3047
+ this.logger.trackAPICall('SEARCH', tableName, 1);
3021
3048
  const response = await this.client.searchRecords(tableName, query, 1);
3022
3049
  if (response.success) {
3023
3050
  // Estimate count based on response
@@ -14,6 +14,7 @@
14
14
  declare class ServiceNowOperationsMCP {
15
15
  private server;
16
16
  private client;
17
+ private logger;
17
18
  constructor();
18
19
  private setupToolHandlers;
19
20
  private handleUniversalQuery;