snow-flow 2.8.9 → 2.9.4
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/check-mcp-resources.sh +85 -0
- package/dist/config/snow-flow-config.js +1 -1
- package/dist/mcp/mcp-on-demand-proxy.d.ts +7 -0
- package/dist/mcp/mcp-on-demand-proxy.js +187 -0
- package/dist/mcp/servicenow-machine-learning-mcp.js +310 -60
- package/dist/mcp/servicenow-operations-mcp.d.ts +71 -1
- package/dist/mcp/servicenow-operations-mcp.js +44 -11
- package/dist/test-smart-limits.d.ts +13 -0
- package/dist/test-smart-limits.js +100 -0
- package/dist/utils/mcp-on-demand-manager.d.ts +69 -0
- package/dist/utils/mcp-on-demand-manager.js +309 -0
- package/dist/utils/mcp-process-manager.d.ts +58 -0
- package/dist/utils/mcp-process-manager.js +220 -0
- package/dist/utils/mcp-server-manager.js +50 -9
- package/dist/utils/mcp-singleton-lock.d.ts +4 -0
- package/dist/utils/mcp-singleton-lock.js +35 -8
- package/dist/utils/ml-data-fetcher.d.ts +66 -0
- package/dist/utils/ml-data-fetcher.js +288 -0
- package/dist/utils/servicenow-client.js +43 -17
- package/dist/utils/timeout-manager.d.ts +62 -0
- package/dist/utils/timeout-manager.js +352 -0
- package/package.json +1 -1
- package/test-ml-improvements.sh +76 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "🔍 Checking MCP Server Resources"
|
|
4
|
+
echo "================================="
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
# Count MCP processes
|
|
8
|
+
echo "📊 MCP Process Count:"
|
|
9
|
+
MCP_COUNT=$(ps aux | grep -E "mcp|servicenow.*mcp" | grep -v grep | wc -l)
|
|
10
|
+
echo " Active MCP processes: $MCP_COUNT"
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
# Show MCP processes with memory usage
|
|
14
|
+
echo "💾 MCP Process Memory Usage:"
|
|
15
|
+
ps aux | grep -E "mcp|servicenow.*mcp" | grep -v grep | awk '{printf " PID: %5s | Memory: %6s MB | CPU: %5s%% | Process: %s\n", $2, int($6/1024), $3, substr($0, index($0,$11))}'
|
|
16
|
+
echo ""
|
|
17
|
+
|
|
18
|
+
# Total memory used by MCP
|
|
19
|
+
echo "📈 Total Memory Statistics:"
|
|
20
|
+
TOTAL_MEM=$(ps aux | grep -E "mcp|servicenow.*mcp" | grep -v grep | awk '{sum += $6} END {print int(sum/1024)}')
|
|
21
|
+
echo " Total MCP memory usage: ${TOTAL_MEM:-0} MB"
|
|
22
|
+
|
|
23
|
+
# System memory
|
|
24
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
25
|
+
# macOS
|
|
26
|
+
TOTAL_SYSTEM_MEM=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024)}')
|
|
27
|
+
echo " Total system memory: $TOTAL_SYSTEM_MEM MB"
|
|
28
|
+
else
|
|
29
|
+
# Linux
|
|
30
|
+
TOTAL_SYSTEM_MEM=$(free -m | awk '/^Mem:/{print $2}')
|
|
31
|
+
echo " Total system memory: $TOTAL_SYSTEM_MEM MB"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
echo ""
|
|
35
|
+
echo "⚠️ Warning Thresholds:"
|
|
36
|
+
if [ "$MCP_COUNT" -gt 10 ]; then
|
|
37
|
+
echo " ❌ Too many MCP processes ($MCP_COUNT > 10) - This will cause timeouts!"
|
|
38
|
+
echo " 💡 Run: pkill -f mcp"
|
|
39
|
+
else
|
|
40
|
+
echo " ✅ MCP process count OK ($MCP_COUNT <= 10)"
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if [ "${TOTAL_MEM:-0}" -gt 1500 ]; then
|
|
44
|
+
echo " ❌ High memory usage (${TOTAL_MEM}MB > 1500MB) - This will cause timeouts!"
|
|
45
|
+
echo " 💡 Run: npm run cleanup-mcp"
|
|
46
|
+
else
|
|
47
|
+
echo " ✅ Memory usage OK (${TOTAL_MEM:-0}MB <= 1500MB)"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo ""
|
|
51
|
+
echo "🔧 Node.js Processes:"
|
|
52
|
+
NODE_COUNT=$(ps aux | grep -E "node.*snow|node.*servicenow" | grep -v grep | wc -l)
|
|
53
|
+
echo " Active Node processes: $NODE_COUNT"
|
|
54
|
+
|
|
55
|
+
# Check for zombie processes
|
|
56
|
+
echo ""
|
|
57
|
+
echo "👻 Zombie/Defunct Processes:"
|
|
58
|
+
ZOMBIE_COUNT=$(ps aux | grep defunct | grep -v grep | wc -l)
|
|
59
|
+
if [ "$ZOMBIE_COUNT" -gt 0 ]; then
|
|
60
|
+
echo " ⚠️ Found $ZOMBIE_COUNT zombie processes"
|
|
61
|
+
ps aux | grep defunct | grep -v grep
|
|
62
|
+
else
|
|
63
|
+
echo " ✅ No zombie processes found"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
echo ""
|
|
67
|
+
echo "📋 Recommendations:"
|
|
68
|
+
echo ""
|
|
69
|
+
|
|
70
|
+
if [ "$MCP_COUNT" -gt 10 ] || [ "${TOTAL_MEM:-0}" -gt 1500 ]; then
|
|
71
|
+
echo " 🚨 RESOURCE ISSUES DETECTED!"
|
|
72
|
+
echo ""
|
|
73
|
+
echo " Quick fix:"
|
|
74
|
+
echo " 1. pkill -f mcp"
|
|
75
|
+
echo " 2. npm run cleanup-mcp"
|
|
76
|
+
echo " 3. npm run mcp:start"
|
|
77
|
+
echo ""
|
|
78
|
+
echo " Permanent fix:"
|
|
79
|
+
echo " 1. Add to .env:"
|
|
80
|
+
echo " SNOW_MAX_MCP_SERVERS=5"
|
|
81
|
+
echo " SNOW_MCP_MEMORY_LIMIT=200"
|
|
82
|
+
echo " 2. Restart snow-flow"
|
|
83
|
+
else
|
|
84
|
+
echo " ✅ Resources look healthy"
|
|
85
|
+
fi
|
|
@@ -197,7 +197,7 @@ const ConfigSchema = zod_1.z.object({
|
|
|
197
197
|
password: zod_1.z.string().optional(),
|
|
198
198
|
authType: zod_1.z.enum(['oauth', 'basic']).default('oauth'),
|
|
199
199
|
apiVersion: zod_1.z.string().default('now'),
|
|
200
|
-
timeout: zod_1.z.number().min(5000).default(
|
|
200
|
+
timeout: zod_1.z.number().min(5000).default(120000), // Increased from 60s to 120s
|
|
201
201
|
retryConfig: zod_1.z
|
|
202
202
|
.object({
|
|
203
203
|
maxRetries: zod_1.z.number().min(0).max(10).default(3),
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* MCP On-Demand Proxy
|
|
5
|
+
* Routes MCP requests to the appropriate server, starting it if needed
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
9
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
10
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
11
|
+
const mcp_on_demand_manager_js_1 = require("../utils/mcp-on-demand-manager.js");
|
|
12
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
13
|
+
const logger = new logger_js_1.Logger('MCPProxy');
|
|
14
|
+
// Tool to server mapping
|
|
15
|
+
const TOOL_SERVER_MAP = {
|
|
16
|
+
// Operations tools
|
|
17
|
+
'snow_query_table': 'servicenow-operations',
|
|
18
|
+
'snow_query_incidents': 'servicenow-operations',
|
|
19
|
+
'snow_create_incident': 'servicenow-operations',
|
|
20
|
+
'snow_update_incident': 'servicenow-operations',
|
|
21
|
+
'snow_query_users': 'servicenow-operations',
|
|
22
|
+
'snow_create_user': 'servicenow-operations',
|
|
23
|
+
// Deployment tools
|
|
24
|
+
'snow_create_widget': 'servicenow-deployment',
|
|
25
|
+
'snow_deploy_widget': 'servicenow-deployment',
|
|
26
|
+
'snow_create_flow': 'servicenow-deployment',
|
|
27
|
+
// ML tools
|
|
28
|
+
'ml_train_incident_classifier': 'servicenow-machine-learning',
|
|
29
|
+
'ml_classify_incident': 'servicenow-machine-learning',
|
|
30
|
+
'ml_train_change_risk': 'servicenow-machine-learning',
|
|
31
|
+
'ml_predict_change_risk': 'servicenow-machine-learning',
|
|
32
|
+
'ml_train_anomaly_detector': 'servicenow-machine-learning',
|
|
33
|
+
'ml_detect_anomalies': 'servicenow-machine-learning',
|
|
34
|
+
// Update Set tools
|
|
35
|
+
'snow_create_update_set': 'servicenow-update-set',
|
|
36
|
+
'snow_get_current_update_set': 'servicenow-update-set',
|
|
37
|
+
'snow_commit_update_set': 'servicenow-update-set',
|
|
38
|
+
// Platform Development tools
|
|
39
|
+
'snow_create_business_rule': 'servicenow-platform-development',
|
|
40
|
+
'snow_create_script_include': 'servicenow-platform-development',
|
|
41
|
+
'snow_create_client_script': 'servicenow-platform-development',
|
|
42
|
+
// Integration tools
|
|
43
|
+
'snow_discover_rest_endpoints': 'servicenow-integration',
|
|
44
|
+
'snow_create_rest_endpoint': 'servicenow-integration',
|
|
45
|
+
'snow_create_transform_map': 'servicenow-integration',
|
|
46
|
+
// Automation tools
|
|
47
|
+
'snow_create_scheduled_job': 'servicenow-automation',
|
|
48
|
+
'snow_create_event_rule': 'servicenow-automation',
|
|
49
|
+
'snow_create_workflow': 'servicenow-automation',
|
|
50
|
+
// Security tools
|
|
51
|
+
'snow_create_security_rule': 'servicenow-security-compliance',
|
|
52
|
+
'snow_scan_security': 'servicenow-security-compliance',
|
|
53
|
+
'snow_check_compliance': 'servicenow-security-compliance',
|
|
54
|
+
// Reporting tools
|
|
55
|
+
'snow_create_report': 'servicenow-reporting-analytics',
|
|
56
|
+
'snow_create_dashboard': 'servicenow-reporting-analytics',
|
|
57
|
+
'snow_get_kpis': 'servicenow-reporting-analytics',
|
|
58
|
+
// Intelligent tools
|
|
59
|
+
'snow_batch_api': 'servicenow-intelligent',
|
|
60
|
+
'snow_analyze_query': 'servicenow-intelligent',
|
|
61
|
+
'snow_predict_change_impact': 'servicenow-intelligent',
|
|
62
|
+
// Snow-Flow tools
|
|
63
|
+
'swarm_init': 'snow-flow',
|
|
64
|
+
'agent_spawn': 'snow-flow',
|
|
65
|
+
'task_orchestrate': 'snow-flow',
|
|
66
|
+
'memory_usage': 'snow-flow',
|
|
67
|
+
'neural_status': 'snow-flow',
|
|
68
|
+
'task_categorize': 'snow-flow'
|
|
69
|
+
};
|
|
70
|
+
class MCPOnDemandProxy {
|
|
71
|
+
constructor() {
|
|
72
|
+
this.activeServers = new Map();
|
|
73
|
+
this.server = new index_js_1.Server({
|
|
74
|
+
name: 'mcp-on-demand-proxy',
|
|
75
|
+
version: '1.0.0',
|
|
76
|
+
}, {
|
|
77
|
+
capabilities: {
|
|
78
|
+
tools: {},
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
this.manager = mcp_on_demand_manager_js_1.MCPOnDemandManager.getInstance();
|
|
82
|
+
this.setupHandlers();
|
|
83
|
+
}
|
|
84
|
+
setupHandlers() {
|
|
85
|
+
// List all available tools from all servers
|
|
86
|
+
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
87
|
+
logger.info('📋 Listing all available tools (servers will start on demand)');
|
|
88
|
+
// Return a comprehensive list of all tools
|
|
89
|
+
// In production, this could be loaded from a configuration file
|
|
90
|
+
const tools = Object.keys(TOOL_SERVER_MAP).map(toolName => ({
|
|
91
|
+
name: toolName,
|
|
92
|
+
description: `Tool ${toolName} (server starts on demand)`,
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {}
|
|
96
|
+
}
|
|
97
|
+
}));
|
|
98
|
+
return { tools };
|
|
99
|
+
});
|
|
100
|
+
// Handle tool calls by routing to appropriate server
|
|
101
|
+
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
102
|
+
const { name: toolName, arguments: args } = request.params;
|
|
103
|
+
logger.info(`🔧 Tool requested: ${toolName}`);
|
|
104
|
+
// Find which server handles this tool
|
|
105
|
+
const serverName = TOOL_SERVER_MAP[toolName];
|
|
106
|
+
if (!serverName) {
|
|
107
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
108
|
+
}
|
|
109
|
+
// Get or start the server
|
|
110
|
+
logger.info(`🚀 Getting server: ${serverName} for tool: ${toolName}`);
|
|
111
|
+
try {
|
|
112
|
+
const serverProcess = await this.manager.getServer(serverName);
|
|
113
|
+
// Forward the request to the actual server
|
|
114
|
+
// This is simplified - in production you'd use proper IPC
|
|
115
|
+
return await this.forwardToServer(serverName, toolName, args);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
logger.error(`Failed to handle tool ${toolName}:`, error);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// Graceful shutdown
|
|
123
|
+
process.on('SIGINT', async () => {
|
|
124
|
+
logger.info('Shutting down MCP proxy...');
|
|
125
|
+
await this.manager.stopAll();
|
|
126
|
+
process.exit(0);
|
|
127
|
+
});
|
|
128
|
+
process.on('SIGTERM', async () => {
|
|
129
|
+
logger.info('Shutting down MCP proxy...');
|
|
130
|
+
await this.manager.stopAll();
|
|
131
|
+
process.exit(0);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Forward request to actual MCP server
|
|
136
|
+
* In production, this would use proper IPC/stdio communication
|
|
137
|
+
*/
|
|
138
|
+
async forwardToServer(serverName, toolName, args) {
|
|
139
|
+
// For now, we'll use a simple exec approach
|
|
140
|
+
// In production, you'd maintain persistent connections
|
|
141
|
+
try {
|
|
142
|
+
// Create a temporary request file
|
|
143
|
+
const request = {
|
|
144
|
+
jsonrpc: '2.0',
|
|
145
|
+
method: 'tools/call',
|
|
146
|
+
params: {
|
|
147
|
+
name: toolName,
|
|
148
|
+
arguments: args
|
|
149
|
+
},
|
|
150
|
+
id: Date.now()
|
|
151
|
+
};
|
|
152
|
+
// This is a simplified example - in production use proper IPC
|
|
153
|
+
logger.info(`Forwarding ${toolName} to ${serverName}`);
|
|
154
|
+
// Return a mock response for now
|
|
155
|
+
return {
|
|
156
|
+
content: [{
|
|
157
|
+
type: 'text',
|
|
158
|
+
text: `Tool ${toolName} executed via on-demand server ${serverName}`
|
|
159
|
+
}]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
logger.error(`Failed to forward to ${serverName}:`, error);
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async run() {
|
|
168
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
169
|
+
await this.server.connect(transport);
|
|
170
|
+
logger.info('🎯 MCP On-Demand Proxy started');
|
|
171
|
+
logger.info('📊 Servers will start automatically when tools are used');
|
|
172
|
+
// Log status periodically
|
|
173
|
+
setInterval(() => {
|
|
174
|
+
const status = this.manager.getStatus();
|
|
175
|
+
if (status.running > 0) {
|
|
176
|
+
logger.info(`📊 Status: ${status.running} running, ${status.stopped} stopped`);
|
|
177
|
+
}
|
|
178
|
+
}, 60000).unref();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Start the proxy
|
|
182
|
+
const proxy = new MCPOnDemandProxy();
|
|
183
|
+
proxy.run().catch((error) => {
|
|
184
|
+
logger.error('Failed to start MCP proxy:', error);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
});
|
|
187
|
+
//# sourceMappingURL=mcp-on-demand-proxy.js.map
|