snow-flow 3.5.17 → 3.6.1
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/mcp/servicenow-automation-mcp.js +46 -0
- package/dist/mcp/servicenow-local-development-mcp.js +31 -0
- package/dist/mcp/shared/enhanced-base-mcp-server.d.ts +18 -7
- package/dist/mcp/shared/enhanced-base-mcp-server.js +144 -27
- package/dist/templates/claude-md-template.d.ts +2 -1
- package/dist/templates/claude-md-template.js +360 -26
- package/dist/utils/servicenow-audit-logger.d.ts +109 -0
- package/dist/utils/servicenow-audit-logger.js +267 -0
- package/dist/utils/servicenow-client-with-tracking.d.ts +4 -0
- package/dist/utils/servicenow-client-with-tracking.js +6 -0
- package/package.json +2 -2
|
@@ -13,6 +13,7 @@ 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
15
|
const mcp_logger_js_1 = require("./shared/mcp-logger.js");
|
|
16
|
+
const servicenow_audit_logger_js_1 = require("../utils/servicenow-audit-logger.js");
|
|
16
17
|
class ServiceNowAutomationMCP {
|
|
17
18
|
constructor() {
|
|
18
19
|
this.server = new index_js_1.Server({
|
|
@@ -25,6 +26,8 @@ class ServiceNowAutomationMCP {
|
|
|
25
26
|
});
|
|
26
27
|
this.client = new servicenow_client_js_1.ServiceNowClient();
|
|
27
28
|
this.logger = new mcp_logger_js_1.MCPLogger('ServiceNowAutomationMCP');
|
|
29
|
+
this.auditLogger = (0, servicenow_audit_logger_js_1.getAuditLogger)(this.logger, 'servicenow-automation');
|
|
30
|
+
this.auditLogger.setServiceNowClient(this.client);
|
|
28
31
|
this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
|
|
29
32
|
this.setupHandlers();
|
|
30
33
|
}
|
|
@@ -1756,10 +1759,22 @@ ${groupedResults.suites.slice(0, 10).map(suite => `- ${suite.name} ${suite.activ
|
|
|
1756
1759
|
* Execute script with output retrieval
|
|
1757
1760
|
*/
|
|
1758
1761
|
async executeScriptWithOutput(args) {
|
|
1762
|
+
const startTime = Date.now();
|
|
1759
1763
|
try {
|
|
1760
1764
|
this.logger.info('Executing script with output retrieval...');
|
|
1761
1765
|
// Create a unique execution ID
|
|
1762
1766
|
const executionId = `snow_flow_exec_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
1767
|
+
// Log script execution start
|
|
1768
|
+
await this.getAuditLogger().logOperation('script_execution_start', 'INFO', {
|
|
1769
|
+
message: 'Starting background script execution with output capture',
|
|
1770
|
+
metadata: {
|
|
1771
|
+
execution_id: executionId,
|
|
1772
|
+
script_length: args.script.length,
|
|
1773
|
+
has_es5_validation: true,
|
|
1774
|
+
capture_logs: args.capture_logs,
|
|
1775
|
+
max_wait: args.max_wait || 5000
|
|
1776
|
+
}
|
|
1777
|
+
});
|
|
1763
1778
|
// Wrap the script to capture output
|
|
1764
1779
|
const wrappedScript = `
|
|
1765
1780
|
var snowFlowOutput = [];
|
|
@@ -1864,6 +1879,27 @@ ${groupedResults.suites.slice(0, 10).map(suite => `- ${suite.name} ${suite.activ
|
|
|
1864
1879
|
this.logger.warn('Could not parse script output:', parseError);
|
|
1865
1880
|
}
|
|
1866
1881
|
}
|
|
1882
|
+
const duration = Date.now() - startTime;
|
|
1883
|
+
const success = scriptOutput?.success !== false;
|
|
1884
|
+
const outputLines = scriptOutput?.output?.length || 0;
|
|
1885
|
+
const errorLines = scriptOutput?.errors?.length || 0;
|
|
1886
|
+
// Log script execution completion with audit
|
|
1887
|
+
await this.getAuditLogger().logScriptExecution('background', duration, success, scriptOutput?.errors || [], outputLines);
|
|
1888
|
+
// Enhanced audit log with detailed execution info
|
|
1889
|
+
await this.getAuditLogger().logOperation('script_execution_complete', success ? 'INFO' : 'ERROR', {
|
|
1890
|
+
message: `Background script execution ${success ? 'completed successfully' : 'failed'}`,
|
|
1891
|
+
duration_ms: duration,
|
|
1892
|
+
metadata: {
|
|
1893
|
+
execution_id: executionId,
|
|
1894
|
+
output_lines: outputLines,
|
|
1895
|
+
error_lines: errorLines,
|
|
1896
|
+
script_success: success,
|
|
1897
|
+
execution_method: 'background_with_output',
|
|
1898
|
+
es5_validated: true,
|
|
1899
|
+
captured_output: !!scriptOutput
|
|
1900
|
+
},
|
|
1901
|
+
success
|
|
1902
|
+
});
|
|
1867
1903
|
return {
|
|
1868
1904
|
content: [{
|
|
1869
1905
|
type: 'text',
|
|
@@ -1872,6 +1908,10 @@ ${groupedResults.suites.slice(0, 10).map(suite => `- ${suite.name} ${suite.activ
|
|
|
1872
1908
|
};
|
|
1873
1909
|
}
|
|
1874
1910
|
catch (error) {
|
|
1911
|
+
const duration = Date.now() - startTime;
|
|
1912
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1913
|
+
// Log failed script execution
|
|
1914
|
+
await this.getAuditLogger().logScriptExecution('background', duration, false, { message: errorMessage, type: 'exception' });
|
|
1875
1915
|
this.logger.error('Failed to execute script with output:', error);
|
|
1876
1916
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to execute script: ${error}`);
|
|
1877
1917
|
}
|
|
@@ -2412,6 +2452,12 @@ ${groupedResults.suites.slice(0, 10).map(suite => `- ${suite.name} ${suite.activ
|
|
|
2412
2452
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Failed to trace execution: ${error}`);
|
|
2413
2453
|
}
|
|
2414
2454
|
}
|
|
2455
|
+
/**
|
|
2456
|
+
* Get audit logger for logging Snow-Flow activities
|
|
2457
|
+
*/
|
|
2458
|
+
getAuditLogger() {
|
|
2459
|
+
return this.auditLogger;
|
|
2460
|
+
}
|
|
2415
2461
|
async run() {
|
|
2416
2462
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
2417
2463
|
await this.server.connect(transport);
|
|
@@ -261,6 +261,7 @@ class ServiceNowLocalDevelopmentMCP extends enhanced_base_mcp_server_js_1.Enhanc
|
|
|
261
261
|
}
|
|
262
262
|
async pullArtifact(args) {
|
|
263
263
|
const { sys_id, table } = args;
|
|
264
|
+
const startTime = Date.now();
|
|
264
265
|
// Add timeout for pull operations
|
|
265
266
|
const PULL_TIMEOUT = 15000; // 15 seconds for pull operations
|
|
266
267
|
try {
|
|
@@ -280,6 +281,13 @@ class ServiceNowLocalDevelopmentMCP extends enhanced_base_mcp_server_js_1.Enhanc
|
|
|
280
281
|
setTimeout(() => reject(new Error(`Pull operation timed out after ${PULL_TIMEOUT / 1000}s`)), PULL_TIMEOUT);
|
|
281
282
|
});
|
|
282
283
|
const artifact = await Promise.race([pullPromise, timeoutPromise]);
|
|
284
|
+
const duration = Date.now() - startTime;
|
|
285
|
+
// Log artifact sync operation
|
|
286
|
+
await this.getAuditLogger().logArtifactSync('pull', artifact.tableName, sys_id, artifact.name, artifact.files.length, duration, true);
|
|
287
|
+
// Special logging for widgets
|
|
288
|
+
if (artifact.tableName === 'sp_widget') {
|
|
289
|
+
await this.getAuditLogger().logWidgetOperation('pull', sys_id, artifact.name, duration, true);
|
|
290
|
+
}
|
|
283
291
|
return {
|
|
284
292
|
content: [
|
|
285
293
|
{
|
|
@@ -290,7 +298,10 @@ class ServiceNowLocalDevelopmentMCP extends enhanced_base_mcp_server_js_1.Enhanc
|
|
|
290
298
|
};
|
|
291
299
|
}
|
|
292
300
|
catch (error) {
|
|
301
|
+
const duration = Date.now() - startTime;
|
|
293
302
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
303
|
+
// Log failed operation
|
|
304
|
+
await this.getAuditLogger().logArtifactSync('pull', table || 'unknown', sys_id, undefined, 0, duration, false);
|
|
294
305
|
return {
|
|
295
306
|
content: [
|
|
296
307
|
{
|
|
@@ -303,8 +314,25 @@ class ServiceNowLocalDevelopmentMCP extends enhanced_base_mcp_server_js_1.Enhanc
|
|
|
303
314
|
}
|
|
304
315
|
async pushArtifact(args) {
|
|
305
316
|
const { sys_id, force = false } = args;
|
|
317
|
+
const startTime = Date.now();
|
|
306
318
|
try {
|
|
307
319
|
const success = await this.syncManager.pushArtifact(sys_id);
|
|
320
|
+
const duration = Date.now() - startTime;
|
|
321
|
+
// Get artifact info for logging
|
|
322
|
+
const localArtifacts = this.syncManager.listLocalArtifacts();
|
|
323
|
+
const artifact = localArtifacts.find(a => a.sys_id === sys_id);
|
|
324
|
+
if (success) {
|
|
325
|
+
// Log successful push
|
|
326
|
+
await this.getAuditLogger().logArtifactSync('push', artifact?.tableName || 'unknown', sys_id, artifact?.name, artifact?.files.length, duration, true);
|
|
327
|
+
// Special logging for widgets
|
|
328
|
+
if (artifact?.tableName === 'sp_widget') {
|
|
329
|
+
await this.getAuditLogger().logWidgetOperation('push', sys_id, artifact.name, duration, true);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// Log failed push
|
|
334
|
+
await this.getAuditLogger().logArtifactSync('push', artifact?.tableName || 'unknown', sys_id, artifact?.name, artifact?.files.length, duration, false);
|
|
335
|
+
}
|
|
308
336
|
return {
|
|
309
337
|
content: [
|
|
310
338
|
{
|
|
@@ -317,7 +345,10 @@ class ServiceNowLocalDevelopmentMCP extends enhanced_base_mcp_server_js_1.Enhanc
|
|
|
317
345
|
};
|
|
318
346
|
}
|
|
319
347
|
catch (error) {
|
|
348
|
+
const duration = Date.now() - startTime;
|
|
320
349
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
350
|
+
// Log failed operation
|
|
351
|
+
await this.getAuditLogger().logArtifactSync('push', 'unknown', sys_id, undefined, 0, duration, false);
|
|
321
352
|
return {
|
|
322
353
|
content: [
|
|
323
354
|
{
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Enhanced Base MCP Server with Logging and
|
|
2
|
+
* Enhanced Base MCP Server with Logging, Token Tracking, and ServiceNow Audit Logging
|
|
3
3
|
*/
|
|
4
4
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
5
5
|
import { ServiceNowClientWithTracking } from '../../utils/servicenow-client-with-tracking.js';
|
|
6
6
|
import { MCPLogger } from './mcp-logger.js';
|
|
7
7
|
import { ServiceNowOAuth } from '../../utils/snow-oauth.js';
|
|
8
|
+
import { ServiceNowAuditLogger } from '../../utils/servicenow-audit-logger.js';
|
|
8
9
|
export interface MCPToolResult {
|
|
9
10
|
content: Array<{
|
|
10
11
|
type: string;
|
|
@@ -16,13 +17,15 @@ export declare abstract class EnhancedBaseMCPServer {
|
|
|
16
17
|
protected server: Server;
|
|
17
18
|
protected client: ServiceNowClientWithTracking;
|
|
18
19
|
protected logger: MCPLogger;
|
|
20
|
+
protected auditLogger: ServiceNowAuditLogger;
|
|
19
21
|
protected oauth: ServiceNowOAuth;
|
|
20
22
|
protected isAuthenticated: boolean;
|
|
23
|
+
protected serverName: string;
|
|
21
24
|
constructor(name: string, version?: string);
|
|
22
25
|
/**
|
|
23
|
-
* Execute tool with enhanced tracking
|
|
26
|
+
* Execute tool with enhanced tracking and audit logging
|
|
24
27
|
*/
|
|
25
|
-
protected executeTool(toolName: string, handler: () => Promise<MCPToolResult
|
|
28
|
+
protected executeTool(toolName: string, handler: () => Promise<MCPToolResult>, params?: any): Promise<MCPToolResult>;
|
|
26
29
|
/**
|
|
27
30
|
* Validate ServiceNow connection with progress
|
|
28
31
|
*/
|
|
@@ -35,19 +38,19 @@ export declare abstract class EnhancedBaseMCPServer {
|
|
|
35
38
|
*/
|
|
36
39
|
protected createResponse(message: string, data?: any): MCPToolResult;
|
|
37
40
|
/**
|
|
38
|
-
* Query table with progress tracking
|
|
41
|
+
* Query table with progress tracking and audit logging
|
|
39
42
|
*/
|
|
40
43
|
protected queryTable(table: string, query: string, limit?: number): Promise<any>;
|
|
41
44
|
/**
|
|
42
|
-
* Create record with tracking
|
|
45
|
+
* Create record with tracking and audit logging
|
|
43
46
|
*/
|
|
44
47
|
protected createRecord(table: string, data: any): Promise<any>;
|
|
45
48
|
/**
|
|
46
|
-
* Update record with tracking
|
|
49
|
+
* Update record with tracking and audit logging
|
|
47
50
|
*/
|
|
48
51
|
protected updateRecord(table: string, sysId: string, data: any): Promise<any>;
|
|
49
52
|
/**
|
|
50
|
-
* Get record with tracking
|
|
53
|
+
* Get record with tracking and audit logging
|
|
51
54
|
*/
|
|
52
55
|
protected getRecord(table: string, sysId: string): Promise<any>;
|
|
53
56
|
/**
|
|
@@ -58,5 +61,13 @@ export declare abstract class EnhancedBaseMCPServer {
|
|
|
58
61
|
* Get logger for direct use
|
|
59
62
|
*/
|
|
60
63
|
getLogger(): MCPLogger;
|
|
64
|
+
/**
|
|
65
|
+
* Get audit logger for direct use
|
|
66
|
+
*/
|
|
67
|
+
getAuditLogger(): ServiceNowAuditLogger;
|
|
68
|
+
/**
|
|
69
|
+
* Cleanup resources and flush audit logs
|
|
70
|
+
*/
|
|
71
|
+
cleanup(): Promise<void>;
|
|
61
72
|
}
|
|
62
73
|
//# sourceMappingURL=enhanced-base-mcp-server.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Enhanced Base MCP Server with Logging and
|
|
3
|
+
* Enhanced Base MCP Server with Logging, Token Tracking, and ServiceNow Audit Logging
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.EnhancedBaseMCPServer = void 0;
|
|
@@ -9,15 +9,21 @@ const servicenow_client_with_tracking_js_1 = require("../../utils/servicenow-cli
|
|
|
9
9
|
const mcp_logger_js_1 = require("./mcp-logger.js");
|
|
10
10
|
const snow_oauth_js_1 = require("../../utils/snow-oauth.js");
|
|
11
11
|
const mcp_auth_middleware_js_1 = require("../../utils/mcp-auth-middleware.js");
|
|
12
|
+
const servicenow_audit_logger_js_1 = require("../../utils/servicenow-audit-logger.js");
|
|
12
13
|
class EnhancedBaseMCPServer {
|
|
13
14
|
constructor(name, version = '1.0.0') {
|
|
14
15
|
this.isAuthenticated = false;
|
|
16
|
+
this.serverName = name;
|
|
15
17
|
// Create enhanced logger
|
|
16
18
|
this.logger = new mcp_logger_js_1.MCPLogger(name);
|
|
19
|
+
// Initialize ServiceNow audit logger
|
|
20
|
+
this.auditLogger = (0, servicenow_audit_logger_js_1.getAuditLogger)(this.logger, name);
|
|
17
21
|
// Log startup
|
|
18
22
|
this.logger.info(`🚀 Starting ${name} MCP Server v${version}`);
|
|
19
23
|
// Create enhanced client with tracking
|
|
20
24
|
this.client = new servicenow_client_with_tracking_js_1.ServiceNowClientWithTracking(this.logger);
|
|
25
|
+
// Connect audit logger to ServiceNow client
|
|
26
|
+
this.auditLogger.setServiceNowClient(this.client.getBaseClient());
|
|
21
27
|
// Initialize OAuth
|
|
22
28
|
this.oauth = new snow_oauth_js_1.ServiceNowOAuth();
|
|
23
29
|
// Create server with capabilities
|
|
@@ -29,13 +35,19 @@ class EnhancedBaseMCPServer {
|
|
|
29
35
|
tools: {},
|
|
30
36
|
},
|
|
31
37
|
});
|
|
38
|
+
// Log server initialization
|
|
39
|
+
this.auditLogger.logOperation('server_initialization', 'INFO', {
|
|
40
|
+
message: `${name} MCP Server v${version} initialized`,
|
|
41
|
+
metadata: { version, capabilities: ['tools'] }
|
|
42
|
+
});
|
|
32
43
|
// Report initialization
|
|
33
|
-
this.logger.info(`✅ ${name} initialized and ready`);
|
|
44
|
+
this.logger.info(`✅ ${name} initialized and ready with audit logging`);
|
|
34
45
|
}
|
|
35
46
|
/**
|
|
36
|
-
* Execute tool with enhanced tracking
|
|
47
|
+
* Execute tool with enhanced tracking and audit logging
|
|
37
48
|
*/
|
|
38
|
-
async executeTool(toolName, handler) {
|
|
49
|
+
async executeTool(toolName, handler, params) {
|
|
50
|
+
const startTime = Date.now();
|
|
39
51
|
// Reset tokens at start of each operation to avoid accumulation
|
|
40
52
|
this.logger.resetTokens();
|
|
41
53
|
// Start operation tracking
|
|
@@ -44,30 +56,57 @@ class EnhancedBaseMCPServer {
|
|
|
44
56
|
// Ensure authentication
|
|
45
57
|
await mcp_auth_middleware_js_1.mcpAuth.ensureAuthenticated();
|
|
46
58
|
this.isAuthenticated = true;
|
|
59
|
+
// Log authentication success
|
|
60
|
+
await this.auditLogger.logAuthOperation('token_refresh', true);
|
|
47
61
|
// Execute the tool handler
|
|
48
62
|
const result = await handler();
|
|
63
|
+
const duration = Date.now() - startTime;
|
|
64
|
+
const tokenUsage = this.logger.getTokenUsage();
|
|
65
|
+
// Log successful tool execution
|
|
66
|
+
await this.auditLogger.logOperation('tool_execution', 'INFO', {
|
|
67
|
+
message: `Successfully executed ${toolName}`,
|
|
68
|
+
duration_ms: duration,
|
|
69
|
+
metadata: {
|
|
70
|
+
tool_name: toolName,
|
|
71
|
+
parameters: params ? JSON.stringify(params) : undefined,
|
|
72
|
+
token_usage: tokenUsage
|
|
73
|
+
},
|
|
74
|
+
success: true
|
|
75
|
+
});
|
|
49
76
|
// Log completion
|
|
50
77
|
this.logger.operationComplete(toolName);
|
|
51
78
|
// Send token usage summary if in Claude
|
|
52
79
|
if (process.send) {
|
|
53
|
-
const usage = this.logger.getTokenUsage();
|
|
54
80
|
process.send({
|
|
55
81
|
type: 'token_usage',
|
|
56
82
|
data: {
|
|
57
83
|
tool: toolName,
|
|
58
|
-
tokens:
|
|
84
|
+
tokens: tokenUsage
|
|
59
85
|
}
|
|
60
86
|
});
|
|
61
87
|
}
|
|
62
88
|
return result;
|
|
63
89
|
}
|
|
64
90
|
catch (error) {
|
|
91
|
+
const duration = Date.now() - startTime;
|
|
92
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
93
|
+
// Log failed tool execution
|
|
94
|
+
await this.auditLogger.logOperation('tool_execution', 'ERROR', {
|
|
95
|
+
message: `Failed to execute ${toolName}: ${errorMessage}`,
|
|
96
|
+
duration_ms: duration,
|
|
97
|
+
metadata: {
|
|
98
|
+
tool_name: toolName,
|
|
99
|
+
parameters: params ? JSON.stringify(params) : undefined,
|
|
100
|
+
error_details: error instanceof Error ? { message: error.message, stack: error.stack } : error
|
|
101
|
+
},
|
|
102
|
+
success: false
|
|
103
|
+
});
|
|
65
104
|
this.logger.error(`Tool execution failed: ${toolName}`, error);
|
|
66
105
|
// Return error as tool result
|
|
67
106
|
return {
|
|
68
107
|
content: [{
|
|
69
108
|
type: 'text',
|
|
70
|
-
text: `❌ Error executing ${toolName}: ${
|
|
109
|
+
text: `❌ Error executing ${toolName}: ${errorMessage}`
|
|
71
110
|
}]
|
|
72
111
|
};
|
|
73
112
|
}
|
|
@@ -133,47 +172,95 @@ class EnhancedBaseMCPServer {
|
|
|
133
172
|
return response;
|
|
134
173
|
}
|
|
135
174
|
/**
|
|
136
|
-
* Query table with progress tracking
|
|
175
|
+
* Query table with progress tracking and audit logging
|
|
137
176
|
*/
|
|
138
177
|
async queryTable(table, query, limit = 10) {
|
|
178
|
+
const startTime = Date.now();
|
|
139
179
|
this.logger.progress(`Querying ${table} table (limit: ${limit})...`);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
180
|
+
try {
|
|
181
|
+
const result = await this.client.searchRecords(table, query, limit);
|
|
182
|
+
const recordCount = result?.data?.result?.length || 0;
|
|
183
|
+
const duration = Date.now() - startTime;
|
|
184
|
+
// Log API call
|
|
185
|
+
await this.auditLogger.logAPICall('searchRecords', table, 'query', recordCount, duration, true);
|
|
186
|
+
this.logger.info(`Query completed: ${recordCount} records found`);
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
const duration = Date.now() - startTime;
|
|
191
|
+
await this.auditLogger.logAPICall('searchRecords', table, 'query', 0, duration, false);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
144
194
|
}
|
|
145
195
|
/**
|
|
146
|
-
* Create record with tracking
|
|
196
|
+
* Create record with tracking and audit logging
|
|
147
197
|
*/
|
|
148
198
|
async createRecord(table, data) {
|
|
199
|
+
const startTime = Date.now();
|
|
149
200
|
this.logger.progress(`Creating ${table} record...`);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
201
|
+
try {
|
|
202
|
+
const result = await this.client.createRecord(table, data);
|
|
203
|
+
const duration = Date.now() - startTime;
|
|
204
|
+
const success = !!result?.success;
|
|
205
|
+
const sysId = result?.data?.result?.sys_id;
|
|
206
|
+
// Log API call with audit
|
|
207
|
+
await this.auditLogger.logAPICall('createRecord', table, 'create', 1, duration, success);
|
|
208
|
+
if (success) {
|
|
209
|
+
this.logger.info(`✅ Created ${table} record: ${sysId}`);
|
|
210
|
+
}
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
const duration = Date.now() - startTime;
|
|
215
|
+
await this.auditLogger.logAPICall('createRecord', table, 'create', 0, duration, false);
|
|
216
|
+
throw error;
|
|
153
217
|
}
|
|
154
|
-
return result;
|
|
155
218
|
}
|
|
156
219
|
/**
|
|
157
|
-
* Update record with tracking
|
|
220
|
+
* Update record with tracking and audit logging
|
|
158
221
|
*/
|
|
159
222
|
async updateRecord(table, sysId, data) {
|
|
223
|
+
const startTime = Date.now();
|
|
160
224
|
this.logger.progress(`Updating ${table} record ${sysId}...`);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
225
|
+
try {
|
|
226
|
+
const result = await this.client.updateRecord(table, sysId, data);
|
|
227
|
+
const duration = Date.now() - startTime;
|
|
228
|
+
const success = !!result?.success;
|
|
229
|
+
// Log API call with audit
|
|
230
|
+
await this.auditLogger.logAPICall('updateRecord', table, 'update', 1, duration, success);
|
|
231
|
+
if (success) {
|
|
232
|
+
this.logger.info(`✅ Updated ${table} record: ${sysId}`);
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
const duration = Date.now() - startTime;
|
|
238
|
+
await this.auditLogger.logAPICall('updateRecord', table, 'update', 0, duration, false);
|
|
239
|
+
throw error;
|
|
164
240
|
}
|
|
165
|
-
return result;
|
|
166
241
|
}
|
|
167
242
|
/**
|
|
168
|
-
* Get record with tracking
|
|
243
|
+
* Get record with tracking and audit logging
|
|
169
244
|
*/
|
|
170
245
|
async getRecord(table, sysId) {
|
|
246
|
+
const startTime = Date.now();
|
|
171
247
|
this.logger.progress(`Getting ${table} record ${sysId}...`);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
248
|
+
try {
|
|
249
|
+
const result = await this.client.getRecord(table, sysId);
|
|
250
|
+
const duration = Date.now() - startTime;
|
|
251
|
+
const success = !!result?.success;
|
|
252
|
+
// Log API call with audit
|
|
253
|
+
await this.auditLogger.logAPICall('getRecord', table, 'read', success ? 1 : 0, duration, success);
|
|
254
|
+
if (success) {
|
|
255
|
+
this.logger.info(`✅ Retrieved ${table} record: ${sysId}`);
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
const duration = Date.now() - startTime;
|
|
261
|
+
await this.auditLogger.logAPICall('getRecord', table, 'read', 0, duration, false);
|
|
262
|
+
throw error;
|
|
175
263
|
}
|
|
176
|
-
return result;
|
|
177
264
|
}
|
|
178
265
|
/**
|
|
179
266
|
* Get client for direct use
|
|
@@ -187,6 +274,36 @@ class EnhancedBaseMCPServer {
|
|
|
187
274
|
getLogger() {
|
|
188
275
|
return this.logger;
|
|
189
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Get audit logger for direct use
|
|
279
|
+
*/
|
|
280
|
+
getAuditLogger() {
|
|
281
|
+
return this.auditLogger;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Cleanup resources and flush audit logs
|
|
285
|
+
*/
|
|
286
|
+
async cleanup() {
|
|
287
|
+
this.logger.info(`🧹 Cleaning up ${this.serverName} MCP Server`);
|
|
288
|
+
try {
|
|
289
|
+
// Flush pending audit logs
|
|
290
|
+
await this.auditLogger.flush();
|
|
291
|
+
// Log server shutdown
|
|
292
|
+
await this.auditLogger.logOperation('server_shutdown', 'INFO', {
|
|
293
|
+
message: `${this.serverName} MCP Server shutting down`,
|
|
294
|
+
metadata: {
|
|
295
|
+
uptime_ms: Date.now() - this.logger['startTime'],
|
|
296
|
+
final_token_usage: this.logger.getTokenUsage()
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
// Stop progress indicators
|
|
300
|
+
this.logger.stopProgress();
|
|
301
|
+
this.logger.info(`✅ ${this.serverName} cleanup completed`);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
this.logger.error('Error during cleanup', error);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
190
307
|
}
|
|
191
308
|
exports.EnhancedBaseMCPServer = EnhancedBaseMCPServer;
|
|
192
309
|
//# sourceMappingURL=enhanced-base-mcp-server.js.map
|