snow-flow 3.2.3 → 3.3.0
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/README.md +14 -0
- package/dist/dynamic-version.js +1 -1
- package/dist/mcp/servicenow-knowledge-catalog-mcp-enhanced.d.ts +7 -0
- package/dist/mcp/servicenow-knowledge-catalog-mcp-enhanced.js +207 -0
- package/dist/mcp/shared/enhanced-base-mcp-server.d.ts +53 -0
- package/dist/mcp/shared/enhanced-base-mcp-server.js +168 -0
- package/dist/mcp/shared/mcp-logger.d.ts +80 -0
- package/dist/mcp/shared/mcp-logger.js +190 -0
- package/dist/utils/servicenow-client-with-tracking.d.ts +38 -0
- package/dist/utils/servicenow-client-with-tracking.js +137 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -44,6 +44,20 @@ Snow-Flow connects directly to ServiceNow instances through OAuth 2.0 authentica
|
|
|
44
44
|
- Natural language interface for ServiceNow operations
|
|
45
45
|
- Machine learning capabilities using TensorFlow.js
|
|
46
46
|
- Process automation and workflow optimization
|
|
47
|
+
- Real-time logging and token tracking for API operations
|
|
48
|
+
|
|
49
|
+
### API Operation Visibility
|
|
50
|
+
|
|
51
|
+
Snow-Flow displays detailed information during API calls:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
⏳ Operation in progress... (2s elapsed, 150 tokens used)
|
|
55
|
+
🔄 API Call: GET /api/now/table/incident (10 records)
|
|
56
|
+
📊 Tokens used: 450 (in: 100, out: 350)
|
|
57
|
+
✅ Operation complete in 3 seconds
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
MCP operations run in separate processes and their logs are sent to stderr for visibility in the console.
|
|
47
61
|
|
|
48
62
|
## ServiceNow API Integration
|
|
49
63
|
|
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.
|
|
39
|
+
return '3.3.0';
|
|
40
40
|
}
|
|
41
41
|
// Export a constant that uses the dynamic version
|
|
42
42
|
exports.VERSION = getDynamicVersion();
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* ServiceNow Knowledge Management & Service Catalog MCP Server - ENHANCED VERSION
|
|
5
|
+
* With logging, token tracking, and progress indicators
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
9
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
10
|
+
const enhanced_base_mcp_server_js_1 = require("./shared/enhanced-base-mcp-server.js");
|
|
11
|
+
const mcp_config_manager_js_1 = require("../utils/mcp-config-manager.js");
|
|
12
|
+
class ServiceNowKnowledgeCatalogMCPEnhanced extends enhanced_base_mcp_server_js_1.EnhancedBaseMCPServer {
|
|
13
|
+
constructor() {
|
|
14
|
+
super('servicenow-knowledge-catalog-enhanced', '2.0.0');
|
|
15
|
+
this.config = mcp_config_manager_js_1.mcpConfig.getConfig();
|
|
16
|
+
this.setupHandlers();
|
|
17
|
+
}
|
|
18
|
+
setupHandlers() {
|
|
19
|
+
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
20
|
+
tools: [
|
|
21
|
+
// Knowledge Management Tools
|
|
22
|
+
{
|
|
23
|
+
name: 'snow_create_knowledge_article',
|
|
24
|
+
description: 'Creates a knowledge article in ServiceNow Knowledge Base using kb_knowledge table.',
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
short_description: { type: 'string', description: 'Article title' },
|
|
29
|
+
text: { type: 'string', description: 'Article content (HTML supported)' },
|
|
30
|
+
kb_knowledge_base: { type: 'string', description: 'Knowledge base sys_id or name' },
|
|
31
|
+
kb_category: { type: 'string', description: 'Category sys_id or name' },
|
|
32
|
+
article_type: { type: 'string', description: 'Type: text, html, wiki' },
|
|
33
|
+
workflow_state: { type: 'string', description: 'State: draft, review, published, retired' },
|
|
34
|
+
valid_to: { type: 'string', description: 'Expiration date (YYYY-MM-DD)' },
|
|
35
|
+
meta_description: { type: 'string', description: 'SEO meta description' },
|
|
36
|
+
keywords: { type: 'array', items: { type: 'string' }, description: 'Search keywords' },
|
|
37
|
+
author: { type: 'string', description: 'Author user sys_id or username' }
|
|
38
|
+
},
|
|
39
|
+
required: ['short_description', 'text']
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'snow_search_knowledge',
|
|
44
|
+
description: 'Searches knowledge articles in kb_knowledge table with full-text search.',
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
query: { type: 'string', description: 'Search query text' },
|
|
49
|
+
kb_knowledge_base: { type: 'string', description: 'Filter by knowledge base' },
|
|
50
|
+
kb_category: { type: 'string', description: 'Filter by category' },
|
|
51
|
+
workflow_state: { type: 'string', description: 'Filter by state (published, draft, etc.)' },
|
|
52
|
+
limit: { type: 'number', description: 'Maximum results to return', default: 10 },
|
|
53
|
+
include_content: { type: 'boolean', description: 'Include full article content', default: false }
|
|
54
|
+
},
|
|
55
|
+
required: ['query']
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
// ... other tools omitted for brevity
|
|
59
|
+
]
|
|
60
|
+
}));
|
|
61
|
+
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
62
|
+
try {
|
|
63
|
+
const { name, arguments: args } = request.params;
|
|
64
|
+
// Execute with enhanced tracking
|
|
65
|
+
return await this.executeTool(name, async () => {
|
|
66
|
+
switch (name) {
|
|
67
|
+
case 'snow_create_knowledge_article':
|
|
68
|
+
return await this.createKnowledgeArticle(args);
|
|
69
|
+
case 'snow_search_knowledge':
|
|
70
|
+
return await this.searchKnowledge(args);
|
|
71
|
+
default:
|
|
72
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof types_js_1.McpError)
|
|
78
|
+
throw error;
|
|
79
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Tool execution failed: ${error}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create Knowledge Article with enhanced tracking
|
|
85
|
+
*/
|
|
86
|
+
async createKnowledgeArticle(args) {
|
|
87
|
+
this.logger.info('Creating knowledge article...', {
|
|
88
|
+
title: args.short_description,
|
|
89
|
+
hasContent: !!args.text,
|
|
90
|
+
contentLength: args.text?.length
|
|
91
|
+
});
|
|
92
|
+
// Validate connection
|
|
93
|
+
const connCheck = await this.validateConnection();
|
|
94
|
+
if (!connCheck.success) {
|
|
95
|
+
return this.createResponse(`❌ Connection failed: ${connCheck.error}`);
|
|
96
|
+
}
|
|
97
|
+
// Progress indicator
|
|
98
|
+
this.logger.progress('Building knowledge article data...');
|
|
99
|
+
const articleData = {
|
|
100
|
+
short_description: args.short_description,
|
|
101
|
+
text: args.text,
|
|
102
|
+
kb_knowledge_base: args.kb_knowledge_base || '',
|
|
103
|
+
kb_category: args.kb_category || '',
|
|
104
|
+
article_type: args.article_type || 'text',
|
|
105
|
+
workflow_state: args.workflow_state || 'draft',
|
|
106
|
+
valid_to: args.valid_to || '',
|
|
107
|
+
meta_description: args.meta_description || '',
|
|
108
|
+
keywords: args.keywords?.join(',') || '',
|
|
109
|
+
author: args.author || ''
|
|
110
|
+
};
|
|
111
|
+
this.logger.progress('Creating article in ServiceNow...');
|
|
112
|
+
// Create with tracking
|
|
113
|
+
const response = await this.createRecord('kb_knowledge', articleData);
|
|
114
|
+
if (!response.success) {
|
|
115
|
+
this.logger.error('Failed to create knowledge article', response.error);
|
|
116
|
+
return this.createResponse(`❌ Failed to create article: ${response.error}`);
|
|
117
|
+
}
|
|
118
|
+
// Success with details
|
|
119
|
+
const result = response.data;
|
|
120
|
+
this.logger.info('✅ Knowledge article created successfully', {
|
|
121
|
+
sys_id: result.sys_id,
|
|
122
|
+
number: result.number,
|
|
123
|
+
title: args.short_description
|
|
124
|
+
});
|
|
125
|
+
return this.createResponse(`✅ Knowledge Article created successfully!
|
|
126
|
+
|
|
127
|
+
📚 **${args.short_description}**
|
|
128
|
+
🆔 sys_id: ${result.sys_id}
|
|
129
|
+
📋 Number: ${result.number}
|
|
130
|
+
📊 State: ${args.workflow_state || 'draft'}
|
|
131
|
+
📝 Type: ${args.article_type || 'text'}
|
|
132
|
+
${args.kb_knowledge_base ? `📁 Knowledge Base: ${args.kb_knowledge_base}` : ''}
|
|
133
|
+
${args.kb_category ? `🏷️ Category: ${args.kb_category}` : ''}
|
|
134
|
+
${args.valid_to ? `📅 Valid Until: ${args.valid_to}` : ''}
|
|
135
|
+
|
|
136
|
+
✨ Article created and ready for review!`);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Search Knowledge with enhanced tracking
|
|
140
|
+
*/
|
|
141
|
+
async searchKnowledge(args) {
|
|
142
|
+
this.logger.info('Searching knowledge articles...', {
|
|
143
|
+
query: args.query,
|
|
144
|
+
limit: args.limit || 10,
|
|
145
|
+
includeContent: args.include_content
|
|
146
|
+
});
|
|
147
|
+
// Build query
|
|
148
|
+
let query = `short_descriptionLIKE${args.query}^ORtextLIKE${args.query}`;
|
|
149
|
+
if (args.kb_knowledge_base) {
|
|
150
|
+
query += `^kb_knowledge_base=${args.kb_knowledge_base}`;
|
|
151
|
+
}
|
|
152
|
+
if (args.kb_category) {
|
|
153
|
+
query += `^kb_category=${args.kb_category}`;
|
|
154
|
+
}
|
|
155
|
+
if (args.workflow_state) {
|
|
156
|
+
query += `^workflow_state=${args.workflow_state}`;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
query += '^workflow_state=published'; // Default to published only
|
|
160
|
+
}
|
|
161
|
+
this.logger.progress(`Searching kb_knowledge table for: "${args.query}"...`);
|
|
162
|
+
// Search with tracking
|
|
163
|
+
const limit = args.limit || 10;
|
|
164
|
+
const response = await this.queryTable('kb_knowledge', query, limit);
|
|
165
|
+
if (!response.success) {
|
|
166
|
+
this.logger.error('Knowledge search failed', response.error);
|
|
167
|
+
return this.createResponse(`❌ Search failed: ${response.error}`);
|
|
168
|
+
}
|
|
169
|
+
const articles = response.data.result;
|
|
170
|
+
if (!articles.length) {
|
|
171
|
+
this.logger.info('No articles found', { query: args.query });
|
|
172
|
+
return this.createResponse(`❌ No knowledge articles found matching "${args.query}"`);
|
|
173
|
+
}
|
|
174
|
+
this.logger.info(`Found ${articles.length} knowledge articles`);
|
|
175
|
+
// Format results
|
|
176
|
+
const articleList = articles.map((article) => {
|
|
177
|
+
const snippet = args.include_content ?
|
|
178
|
+
article.text?.substring(0, 200) + '...' :
|
|
179
|
+
article.short_description;
|
|
180
|
+
return `📄 **${article.short_description}**
|
|
181
|
+
🆔 ${article.sys_id}
|
|
182
|
+
📊 State: ${article.workflow_state}
|
|
183
|
+
📅 Updated: ${article.sys_updated_on}
|
|
184
|
+
${args.include_content ? `📝 ${snippet}` : ''}`;
|
|
185
|
+
}).join('\n\n');
|
|
186
|
+
return this.createResponse(`🔍 Knowledge Search Results for "${args.query}":
|
|
187
|
+
|
|
188
|
+
${articleList}
|
|
189
|
+
|
|
190
|
+
✨ Found ${articles.length} article(s)`);
|
|
191
|
+
}
|
|
192
|
+
async start() {
|
|
193
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
194
|
+
await this.server.connect(transport);
|
|
195
|
+
// Log ready state
|
|
196
|
+
this.logger.info('🚀 ServiceNow Knowledge & Catalog MCP Server (Enhanced) running');
|
|
197
|
+
this.logger.info('📊 Token tracking enabled');
|
|
198
|
+
this.logger.info('⏳ Progress indicators active');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Start the enhanced server
|
|
202
|
+
const server = new ServiceNowKnowledgeCatalogMCPEnhanced();
|
|
203
|
+
server.start().catch((error) => {
|
|
204
|
+
console.error('Failed to start enhanced server:', error);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
});
|
|
207
|
+
//# sourceMappingURL=servicenow-knowledge-catalog-mcp-enhanced.js.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Base MCP Server with Logging and Token Tracking
|
|
3
|
+
*/
|
|
4
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
5
|
+
import { ServiceNowClientWithTracking } from '../../utils/servicenow-client-with-tracking.js';
|
|
6
|
+
import { MCPLogger } from './mcp-logger.js';
|
|
7
|
+
import { SnowOAuth } from '../../utils/snow-oauth.js';
|
|
8
|
+
export interface MCPToolResult {
|
|
9
|
+
content: Array<{
|
|
10
|
+
type: string;
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare abstract class EnhancedBaseMCPServer {
|
|
15
|
+
protected server: Server;
|
|
16
|
+
protected client: ServiceNowClientWithTracking;
|
|
17
|
+
protected logger: MCPLogger;
|
|
18
|
+
protected oauth: SnowOAuth;
|
|
19
|
+
protected isAuthenticated: boolean;
|
|
20
|
+
constructor(name: string, version?: string);
|
|
21
|
+
/**
|
|
22
|
+
* Execute tool with enhanced tracking
|
|
23
|
+
*/
|
|
24
|
+
protected executeTool(toolName: string, handler: () => Promise<MCPToolResult>): Promise<MCPToolResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Validate ServiceNow connection with progress
|
|
27
|
+
*/
|
|
28
|
+
protected validateConnection(): Promise<{
|
|
29
|
+
success: boolean;
|
|
30
|
+
error?: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Create standardized response with tracking
|
|
34
|
+
*/
|
|
35
|
+
protected createResponse(message: string, data?: any): MCPToolResult;
|
|
36
|
+
/**
|
|
37
|
+
* Query table with progress tracking
|
|
38
|
+
*/
|
|
39
|
+
protected queryTable(table: string, query: string, limit?: number): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Create record with tracking
|
|
42
|
+
*/
|
|
43
|
+
protected createRecord(table: string, data: any): Promise<any>;
|
|
44
|
+
/**
|
|
45
|
+
* Get client for direct use
|
|
46
|
+
*/
|
|
47
|
+
getClient(): ServiceNowClientWithTracking;
|
|
48
|
+
/**
|
|
49
|
+
* Get logger for direct use
|
|
50
|
+
*/
|
|
51
|
+
getLogger(): MCPLogger;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=enhanced-base-mcp-server.d.ts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced Base MCP Server with Logging and Token Tracking
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EnhancedBaseMCPServer = void 0;
|
|
7
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
8
|
+
const servicenow_client_with_tracking_js_1 = require("../../utils/servicenow-client-with-tracking.js");
|
|
9
|
+
const mcp_logger_js_1 = require("./mcp-logger.js");
|
|
10
|
+
const snow_oauth_js_1 = require("../../utils/snow-oauth.js");
|
|
11
|
+
const mcp_auth_middleware_js_1 = require("../../utils/mcp-auth-middleware.js");
|
|
12
|
+
class EnhancedBaseMCPServer {
|
|
13
|
+
constructor(name, version = '1.0.0') {
|
|
14
|
+
this.isAuthenticated = false;
|
|
15
|
+
// Create enhanced logger
|
|
16
|
+
this.logger = new mcp_logger_js_1.MCPLogger(name);
|
|
17
|
+
// Log startup
|
|
18
|
+
this.logger.info(`🚀 Starting ${name} MCP Server v${version}`);
|
|
19
|
+
// Create enhanced client with tracking
|
|
20
|
+
this.client = new servicenow_client_with_tracking_js_1.ServiceNowClientWithTracking(this.logger);
|
|
21
|
+
// Initialize OAuth
|
|
22
|
+
this.oauth = new snow_oauth_js_1.SnowOAuth();
|
|
23
|
+
// Create server with capabilities
|
|
24
|
+
this.server = new index_js_1.Server({
|
|
25
|
+
name,
|
|
26
|
+
version,
|
|
27
|
+
}, {
|
|
28
|
+
capabilities: {
|
|
29
|
+
tools: {},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
// Report initialization
|
|
33
|
+
this.logger.info(`✅ ${name} initialized and ready`);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Execute tool with enhanced tracking
|
|
37
|
+
*/
|
|
38
|
+
async executeTool(toolName, handler) {
|
|
39
|
+
// Start operation tracking
|
|
40
|
+
this.logger.operationStart(toolName);
|
|
41
|
+
try {
|
|
42
|
+
// Ensure authentication
|
|
43
|
+
await mcp_auth_middleware_js_1.mcpAuth.ensureAuthenticated();
|
|
44
|
+
this.isAuthenticated = true;
|
|
45
|
+
// Execute the tool handler
|
|
46
|
+
const result = await handler();
|
|
47
|
+
// Log completion
|
|
48
|
+
this.logger.operationComplete(toolName);
|
|
49
|
+
// Send token usage summary if in Claude
|
|
50
|
+
if (process.send) {
|
|
51
|
+
const usage = this.logger.getTokenUsage();
|
|
52
|
+
process.send({
|
|
53
|
+
type: 'token_usage',
|
|
54
|
+
data: {
|
|
55
|
+
tool: toolName,
|
|
56
|
+
tokens: usage
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
this.logger.error(`Tool execution failed: ${toolName}`, error);
|
|
64
|
+
// Return error as tool result
|
|
65
|
+
return {
|
|
66
|
+
content: [{
|
|
67
|
+
type: 'text',
|
|
68
|
+
text: `❌ Error executing ${toolName}: ${error instanceof Error ? error.message : String(error)}`
|
|
69
|
+
}]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validate ServiceNow connection with progress
|
|
75
|
+
*/
|
|
76
|
+
async validateConnection() {
|
|
77
|
+
this.logger.progress('Validating ServiceNow connection...');
|
|
78
|
+
try {
|
|
79
|
+
// Check credentials
|
|
80
|
+
const credentials = await this.oauth.loadCredentials();
|
|
81
|
+
if (!credentials) {
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
error: 'No ServiceNow credentials found. Run "snow-flow auth login"'
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Check token
|
|
88
|
+
if (!credentials.accessToken) {
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: 'OAuth authentication required. Run "snow-flow auth login"'
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// Test connection
|
|
95
|
+
this.logger.progress('Testing ServiceNow API connection...');
|
|
96
|
+
const connectionTest = await this.client.testConnection();
|
|
97
|
+
if (!connectionTest.success) {
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: `ServiceNow connection failed: ${connectionTest.error}`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
this.logger.info('✅ ServiceNow connection validated');
|
|
104
|
+
return { success: true };
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
this.logger.error('Connection validation failed', error);
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
error: error instanceof Error ? error.message : String(error)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create standardized response with tracking
|
|
116
|
+
*/
|
|
117
|
+
createResponse(message, data) {
|
|
118
|
+
// Log the response
|
|
119
|
+
this.logger.debug('Tool response', { message, hasData: !!data });
|
|
120
|
+
// Format response
|
|
121
|
+
const response = {
|
|
122
|
+
content: [{
|
|
123
|
+
type: 'text',
|
|
124
|
+
text: message
|
|
125
|
+
}]
|
|
126
|
+
};
|
|
127
|
+
// Add data if provided
|
|
128
|
+
if (data) {
|
|
129
|
+
response.content[0].text += '\n\n' + JSON.stringify(data, null, 2);
|
|
130
|
+
}
|
|
131
|
+
return response;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Query table with progress tracking
|
|
135
|
+
*/
|
|
136
|
+
async queryTable(table, query, limit = 10) {
|
|
137
|
+
this.logger.progress(`Querying ${table} table (limit: ${limit})...`);
|
|
138
|
+
const result = await this.client.searchRecords(table, query, limit);
|
|
139
|
+
const recordCount = result?.data?.result?.length || 0;
|
|
140
|
+
this.logger.info(`Query completed: ${recordCount} records found`);
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Create record with tracking
|
|
145
|
+
*/
|
|
146
|
+
async createRecord(table, data) {
|
|
147
|
+
this.logger.progress(`Creating ${table} record...`);
|
|
148
|
+
const result = await this.client.createRecord(table, data);
|
|
149
|
+
if (result?.success) {
|
|
150
|
+
this.logger.info(`✅ Created ${table} record: ${result.data?.result?.sys_id}`);
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get client for direct use
|
|
156
|
+
*/
|
|
157
|
+
getClient() {
|
|
158
|
+
return this.client;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get logger for direct use
|
|
162
|
+
*/
|
|
163
|
+
getLogger() {
|
|
164
|
+
return this.logger;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.EnhancedBaseMCPServer = EnhancedBaseMCPServer;
|
|
168
|
+
//# sourceMappingURL=enhanced-base-mcp-server.js.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced MCP Logger with Token Tracking and Progress Reporting
|
|
3
|
+
* Sends logs to stderr so they appear in Claude Code console
|
|
4
|
+
*/
|
|
5
|
+
interface TokenUsage {
|
|
6
|
+
input: number;
|
|
7
|
+
output: number;
|
|
8
|
+
total: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class MCPLogger {
|
|
11
|
+
private name;
|
|
12
|
+
private tokenUsage;
|
|
13
|
+
private startTime;
|
|
14
|
+
private lastProgressTime;
|
|
15
|
+
private progressInterval;
|
|
16
|
+
constructor(name: string);
|
|
17
|
+
/**
|
|
18
|
+
* Log to stderr with proper formatting
|
|
19
|
+
*/
|
|
20
|
+
private log;
|
|
21
|
+
/**
|
|
22
|
+
* Start progress indicator for long-running operations
|
|
23
|
+
*/
|
|
24
|
+
private startProgressIndicator;
|
|
25
|
+
/**
|
|
26
|
+
* Stop progress indicator
|
|
27
|
+
*/
|
|
28
|
+
stopProgress(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Log info message
|
|
31
|
+
*/
|
|
32
|
+
info(message: string, data?: any): void;
|
|
33
|
+
/**
|
|
34
|
+
* Log warning message
|
|
35
|
+
*/
|
|
36
|
+
warn(message: string, data?: any): void;
|
|
37
|
+
/**
|
|
38
|
+
* Log error message
|
|
39
|
+
*/
|
|
40
|
+
error(message: string, error?: any): void;
|
|
41
|
+
/**
|
|
42
|
+
* Log debug message
|
|
43
|
+
*/
|
|
44
|
+
debug(message: string, data?: any): void;
|
|
45
|
+
/**
|
|
46
|
+
* Log progress update
|
|
47
|
+
*/
|
|
48
|
+
progress(message: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Track API call
|
|
51
|
+
*/
|
|
52
|
+
trackAPICall(operation: string, table?: string, recordCount?: number): void;
|
|
53
|
+
/**
|
|
54
|
+
* Add token usage
|
|
55
|
+
*/
|
|
56
|
+
addTokens(input: number, output: number): void;
|
|
57
|
+
/**
|
|
58
|
+
* Log operation start
|
|
59
|
+
*/
|
|
60
|
+
operationStart(operation: string, params?: any): void;
|
|
61
|
+
/**
|
|
62
|
+
* Log operation complete
|
|
63
|
+
*/
|
|
64
|
+
operationComplete(operation: string, result?: any): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get token usage
|
|
67
|
+
*/
|
|
68
|
+
getTokenUsage(): TokenUsage;
|
|
69
|
+
/**
|
|
70
|
+
* Reset token usage
|
|
71
|
+
*/
|
|
72
|
+
resetTokens(): void;
|
|
73
|
+
}
|
|
74
|
+
export declare function getGlobalLogger(name?: string): MCPLogger;
|
|
75
|
+
/**
|
|
76
|
+
* Log formatter for consistent output
|
|
77
|
+
*/
|
|
78
|
+
export declare function formatLogMessage(level: string, message: string, data?: any): string;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=mcp-logger.d.ts.map
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced MCP Logger with Token Tracking and Progress Reporting
|
|
4
|
+
* Sends logs to stderr so they appear in Claude Code console
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MCPLogger = void 0;
|
|
8
|
+
exports.getGlobalLogger = getGlobalLogger;
|
|
9
|
+
exports.formatLogMessage = formatLogMessage;
|
|
10
|
+
class MCPLogger {
|
|
11
|
+
constructor(name) {
|
|
12
|
+
this.tokenUsage = { input: 0, output: 0, total: 0 };
|
|
13
|
+
this.startTime = Date.now();
|
|
14
|
+
this.lastProgressTime = Date.now();
|
|
15
|
+
this.progressInterval = null;
|
|
16
|
+
this.name = name;
|
|
17
|
+
// Start progress indicator
|
|
18
|
+
this.startProgressIndicator();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Log to stderr with proper formatting
|
|
22
|
+
*/
|
|
23
|
+
log(level, message, data) {
|
|
24
|
+
const timestamp = new Date().toISOString();
|
|
25
|
+
const logEntry = {
|
|
26
|
+
timestamp,
|
|
27
|
+
level,
|
|
28
|
+
service: this.name,
|
|
29
|
+
message,
|
|
30
|
+
data,
|
|
31
|
+
tokens: this.tokenUsage.total,
|
|
32
|
+
duration: Math.round((Date.now() - this.startTime) / 1000)
|
|
33
|
+
};
|
|
34
|
+
// Send to stderr so it appears in console
|
|
35
|
+
console.error(`[${this.name}] ${level}: ${message}`, data ? JSON.stringify(data, null, 2) : '');
|
|
36
|
+
// Also send structured log for potential parsing
|
|
37
|
+
if (process.send) {
|
|
38
|
+
process.send({
|
|
39
|
+
type: 'log',
|
|
40
|
+
data: logEntry
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Start progress indicator for long-running operations
|
|
46
|
+
*/
|
|
47
|
+
startProgressIndicator() {
|
|
48
|
+
// Send progress every 2 seconds
|
|
49
|
+
this.progressInterval = setInterval(() => {
|
|
50
|
+
const duration = Math.round((Date.now() - this.startTime) / 1000);
|
|
51
|
+
if (duration > 0) {
|
|
52
|
+
this.progress(`Operation in progress... (${duration}s elapsed, ${this.tokenUsage.total} tokens used)`);
|
|
53
|
+
}
|
|
54
|
+
}, 2000);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Stop progress indicator
|
|
58
|
+
*/
|
|
59
|
+
stopProgress() {
|
|
60
|
+
if (this.progressInterval) {
|
|
61
|
+
clearInterval(this.progressInterval);
|
|
62
|
+
this.progressInterval = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Log info message
|
|
67
|
+
*/
|
|
68
|
+
info(message, data) {
|
|
69
|
+
this.log('INFO', message, data);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Log warning message
|
|
73
|
+
*/
|
|
74
|
+
warn(message, data) {
|
|
75
|
+
this.log('WARN', message, data);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Log error message
|
|
79
|
+
*/
|
|
80
|
+
error(message, error) {
|
|
81
|
+
const errorData = error instanceof Error ? {
|
|
82
|
+
message: error.message,
|
|
83
|
+
stack: error.stack,
|
|
84
|
+
name: error.name
|
|
85
|
+
} : error;
|
|
86
|
+
this.log('ERROR', message, errorData);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Log debug message
|
|
90
|
+
*/
|
|
91
|
+
debug(message, data) {
|
|
92
|
+
if (process.env.DEBUG === 'true' || process.env.NODE_ENV === 'development') {
|
|
93
|
+
this.log('DEBUG', message, data);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Log progress update
|
|
98
|
+
*/
|
|
99
|
+
progress(message) {
|
|
100
|
+
// Only log progress if enough time has passed
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
if (now - this.lastProgressTime > 1000) {
|
|
103
|
+
this.lastProgressTime = now;
|
|
104
|
+
console.error(`⏳ [${this.name}] ${message}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Track API call
|
|
109
|
+
*/
|
|
110
|
+
trackAPICall(operation, table, recordCount) {
|
|
111
|
+
const message = `🔄 API Call: ${operation}${table ? ` on ${table}` : ''}${recordCount ? ` (${recordCount} records)` : ''}`;
|
|
112
|
+
this.info(message);
|
|
113
|
+
// Estimate token usage (rough approximation)
|
|
114
|
+
const estimatedTokens = recordCount ? recordCount * 50 : 100;
|
|
115
|
+
this.addTokens(estimatedTokens, 50);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Add token usage
|
|
119
|
+
*/
|
|
120
|
+
addTokens(input, output) {
|
|
121
|
+
this.tokenUsage.input += input;
|
|
122
|
+
this.tokenUsage.output += output;
|
|
123
|
+
this.tokenUsage.total = this.tokenUsage.input + this.tokenUsage.output;
|
|
124
|
+
// Report token usage
|
|
125
|
+
if (this.tokenUsage.total > 0) {
|
|
126
|
+
console.error(`📊 [${this.name}] Tokens used: ${this.tokenUsage.total} (in: ${this.tokenUsage.input}, out: ${this.tokenUsage.output})`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Log operation start
|
|
131
|
+
*/
|
|
132
|
+
operationStart(operation, params) {
|
|
133
|
+
this.startTime = Date.now();
|
|
134
|
+
this.info(`🚀 Starting: ${operation}`, params);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Log operation complete
|
|
138
|
+
*/
|
|
139
|
+
operationComplete(operation, result) {
|
|
140
|
+
const duration = Math.round((Date.now() - this.startTime) / 1000);
|
|
141
|
+
this.stopProgress();
|
|
142
|
+
this.info(`✅ Completed: ${operation} (${duration}s, ${this.tokenUsage.total} tokens)`, result);
|
|
143
|
+
// Send final token report
|
|
144
|
+
if (this.tokenUsage.total > 0) {
|
|
145
|
+
console.error(`
|
|
146
|
+
═══════════════════════════════════════════════════════════
|
|
147
|
+
📊 ${this.name} - Operation Complete
|
|
148
|
+
─────────────────────────────────────────────────────────
|
|
149
|
+
⏱️ Duration: ${duration} seconds
|
|
150
|
+
🔢 Tokens Used: ${this.tokenUsage.total}
|
|
151
|
+
├─ Input: ${this.tokenUsage.input}
|
|
152
|
+
└─ Output: ${this.tokenUsage.output}
|
|
153
|
+
🎯 Operation: ${operation}
|
|
154
|
+
═══════════════════════════════════════════════════════════
|
|
155
|
+
`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get token usage
|
|
160
|
+
*/
|
|
161
|
+
getTokenUsage() {
|
|
162
|
+
return { ...this.tokenUsage };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Reset token usage
|
|
166
|
+
*/
|
|
167
|
+
resetTokens() {
|
|
168
|
+
this.tokenUsage = { input: 0, output: 0, total: 0 };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.MCPLogger = MCPLogger;
|
|
172
|
+
/**
|
|
173
|
+
* Create a singleton logger instance for consistent logging
|
|
174
|
+
*/
|
|
175
|
+
let globalLogger = null;
|
|
176
|
+
function getGlobalLogger(name) {
|
|
177
|
+
if (!globalLogger) {
|
|
178
|
+
globalLogger = new MCPLogger(name || 'MCP-Server');
|
|
179
|
+
}
|
|
180
|
+
return globalLogger;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Log formatter for consistent output
|
|
184
|
+
*/
|
|
185
|
+
function formatLogMessage(level, message, data) {
|
|
186
|
+
const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
|
|
187
|
+
const dataStr = data ? ` | ${JSON.stringify(data)}` : '';
|
|
188
|
+
return `[${timestamp}] ${level.padEnd(5)} | ${message}${dataStr}`;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=mcp-logger.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ServiceNow Client Wrapper with Token & Progress Tracking
|
|
3
|
+
*/
|
|
4
|
+
import { ServiceNowClient } from './servicenow-client.js';
|
|
5
|
+
import { MCPLogger } from '../mcp/shared/mcp-logger.js';
|
|
6
|
+
export declare class ServiceNowClientWithTracking extends ServiceNowClient {
|
|
7
|
+
private mcpLogger;
|
|
8
|
+
constructor(logger?: MCPLogger);
|
|
9
|
+
/**
|
|
10
|
+
* Override makeRequest to add tracking
|
|
11
|
+
*/
|
|
12
|
+
makeRequest(config: any): Promise<any>;
|
|
13
|
+
/**
|
|
14
|
+
* Override searchRecords to add tracking
|
|
15
|
+
*/
|
|
16
|
+
searchRecords(table: string, query: string, limit?: number): Promise<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Override createRecord to add tracking
|
|
19
|
+
*/
|
|
20
|
+
createRecord(table: string, data: any): Promise<any>;
|
|
21
|
+
/**
|
|
22
|
+
* Override updateRecord to add tracking
|
|
23
|
+
*/
|
|
24
|
+
updateRecord(table: string, sysId: string, data: any): Promise<any>;
|
|
25
|
+
/**
|
|
26
|
+
* Override getRecord to add tracking
|
|
27
|
+
*/
|
|
28
|
+
getRecord(table: string, sysId: string, fields?: string[]): Promise<any>;
|
|
29
|
+
/**
|
|
30
|
+
* Extract table name from URL
|
|
31
|
+
*/
|
|
32
|
+
private extractTableFromUrl;
|
|
33
|
+
/**
|
|
34
|
+
* Get logger for external use
|
|
35
|
+
*/
|
|
36
|
+
getLogger(): MCPLogger;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=servicenow-client-with-tracking.d.ts.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ServiceNow Client Wrapper with Token & Progress Tracking
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ServiceNowClientWithTracking = void 0;
|
|
7
|
+
const servicenow_client_js_1 = require("./servicenow-client.js");
|
|
8
|
+
const mcp_logger_js_1 = require("../mcp/shared/mcp-logger.js");
|
|
9
|
+
class ServiceNowClientWithTracking extends servicenow_client_js_1.ServiceNowClient {
|
|
10
|
+
constructor(logger) {
|
|
11
|
+
super();
|
|
12
|
+
this.mcpLogger = logger || new mcp_logger_js_1.MCPLogger('ServiceNow-API');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Override makeRequest to add tracking
|
|
16
|
+
*/
|
|
17
|
+
async makeRequest(config) {
|
|
18
|
+
const operation = `${config.method || 'GET'} ${config.url || config.endpoint}`;
|
|
19
|
+
const table = this.extractTableFromUrl(config.url || config.endpoint);
|
|
20
|
+
// Log API call start
|
|
21
|
+
this.mcpLogger.trackAPICall(operation, table);
|
|
22
|
+
this.mcpLogger.progress(`Calling ServiceNow API: ${operation}`);
|
|
23
|
+
try {
|
|
24
|
+
// Call parent method
|
|
25
|
+
const result = await super.makeRequest(config);
|
|
26
|
+
// Estimate tokens based on response size
|
|
27
|
+
if (result.data) {
|
|
28
|
+
const responseSize = JSON.stringify(result.data).length;
|
|
29
|
+
const estimatedTokens = Math.ceil(responseSize / 4); // Rough estimate: 4 chars per token
|
|
30
|
+
this.mcpLogger.addTokens(50, estimatedTokens); // 50 for request, response based on size
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
this.mcpLogger.error(`API call failed: ${operation}`, error);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Override searchRecords to add tracking
|
|
41
|
+
*/
|
|
42
|
+
async searchRecords(table, query, limit = 10) {
|
|
43
|
+
this.mcpLogger.operationStart(`Search ${table}`, { query, limit });
|
|
44
|
+
try {
|
|
45
|
+
const result = await super.searchRecords(table, query, limit);
|
|
46
|
+
// Track record count
|
|
47
|
+
const recordCount = result?.data?.result?.length || 0;
|
|
48
|
+
this.mcpLogger.info(`Found ${recordCount} ${table} records`);
|
|
49
|
+
// Estimate tokens
|
|
50
|
+
if (result?.data?.result) {
|
|
51
|
+
const dataSize = JSON.stringify(result.data.result).length;
|
|
52
|
+
const estimatedTokens = Math.ceil(dataSize / 4);
|
|
53
|
+
this.mcpLogger.addTokens(100, estimatedTokens);
|
|
54
|
+
}
|
|
55
|
+
this.mcpLogger.operationComplete(`Search ${table}`, { count: recordCount });
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.mcpLogger.error(`Search failed for ${table}`, error);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Override createRecord to add tracking
|
|
65
|
+
*/
|
|
66
|
+
async createRecord(table, data) {
|
|
67
|
+
this.mcpLogger.operationStart(`Create ${table} record`, { fields: Object.keys(data).length });
|
|
68
|
+
try {
|
|
69
|
+
const result = await super.createRecord(table, data);
|
|
70
|
+
// Estimate tokens
|
|
71
|
+
const requestSize = JSON.stringify(data).length;
|
|
72
|
+
const responseSize = JSON.stringify(result).length;
|
|
73
|
+
this.mcpLogger.addTokens(Math.ceil(requestSize / 4), Math.ceil(responseSize / 4));
|
|
74
|
+
this.mcpLogger.operationComplete(`Create ${table} record`, {
|
|
75
|
+
sys_id: result?.data?.result?.sys_id
|
|
76
|
+
});
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
this.mcpLogger.error(`Failed to create ${table} record`, error);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Override updateRecord to add tracking
|
|
86
|
+
*/
|
|
87
|
+
async updateRecord(table, sysId, data) {
|
|
88
|
+
this.mcpLogger.operationStart(`Update ${table} record`, { sys_id: sysId });
|
|
89
|
+
try {
|
|
90
|
+
const result = await super.updateRecord(table, sysId, data);
|
|
91
|
+
// Estimate tokens
|
|
92
|
+
const requestSize = JSON.stringify(data).length;
|
|
93
|
+
const responseSize = JSON.stringify(result).length;
|
|
94
|
+
this.mcpLogger.addTokens(Math.ceil(requestSize / 4), Math.ceil(responseSize / 4));
|
|
95
|
+
this.mcpLogger.operationComplete(`Update ${table} record`);
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
this.mcpLogger.error(`Failed to update ${table} record`, error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Override getRecord to add tracking
|
|
105
|
+
*/
|
|
106
|
+
async getRecord(table, sysId, fields) {
|
|
107
|
+
this.mcpLogger.progress(`Fetching ${table} record: ${sysId}`);
|
|
108
|
+
try {
|
|
109
|
+
const result = await super.getRecord(table, sysId, fields);
|
|
110
|
+
// Estimate tokens
|
|
111
|
+
if (result?.data?.result) {
|
|
112
|
+
const responseSize = JSON.stringify(result.data.result).length;
|
|
113
|
+
this.mcpLogger.addTokens(50, Math.ceil(responseSize / 4));
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.mcpLogger.error(`Failed to get ${table} record`, error);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Extract table name from URL
|
|
124
|
+
*/
|
|
125
|
+
extractTableFromUrl(url) {
|
|
126
|
+
const match = url.match(/\/table\/([^/?]+)/);
|
|
127
|
+
return match ? match[1] : undefined;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get logger for external use
|
|
131
|
+
*/
|
|
132
|
+
getLogger() {
|
|
133
|
+
return this.mcpLogger;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.ServiceNowClientWithTracking = ServiceNowClientWithTracking;
|
|
137
|
+
//# sourceMappingURL=servicenow-client-with-tracking.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "Snow-Flow v3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
|
+
"description": "Snow-Flow v3.3.0: ServiceNow development platform with 180+ MCP tools. Includes API operation logging and token usage tracking. Supports ATF Testing, Knowledge Management, Service Catalog, Change Management, Virtual Agent, Performance Analytics, Flow Designer, Agent Workspace, Mobile, CMDB/Discovery, Event Management, HR Service Delivery, Customer Service Management, and DevOps integration. All tools use official ServiceNow REST APIs across 17 specialized MCP servers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"bin": {
|