snow-flow 8.37.26 ā 8.38.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/.snow-code/agent/deployment-specialist.md +346 -0
- package/.snow-code/agent/orchestrator.md +286 -0
- package/.snow-code/agent/risk-assessor.md +454 -0
- package/.snow-code/agent/solution-architect.md +582 -0
- package/.snow-code/agent/validator.md +503 -0
- package/.snow-code/opencode.json +49 -0
- package/README.md +141 -904
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +93 -256
- package/dist/cli.js.map +1 -1
- package/dist/utils/sync-mcp-configs.d.ts +7 -5
- package/dist/utils/sync-mcp-configs.d.ts.map +1 -1
- package/dist/utils/sync-mcp-configs.js +19 -74
- package/dist/utils/sync-mcp-configs.js.map +1 -1
- package/package.json +2 -3
- package/scripts/check-binary-updates.js +0 -169
- package/scripts/check-npm-version.js +0 -92
- package/scripts/classify-all-tools.ts +0 -446
- package/scripts/classify-edge-cases.ts +0 -275
- package/scripts/classify-operations-tools.sh +0 -96
- package/scripts/cleanup-mcp-servers.js +0 -115
- package/scripts/diagnose-mcp.js +0 -299
- package/scripts/generate-mcp-config.js +0 -45
- package/scripts/mcp-server-manager.sh +0 -320
- package/scripts/postinstall.js +0 -75
- package/scripts/reset-mcp-servers.js +0 -266
- package/scripts/safe-mcp-cleanup.js +0 -151
- package/scripts/setup-mcp.js +0 -106
- package/scripts/start-mcp-proper.js +0 -76
- package/scripts/start-snowcode.sh +0 -123
- package/scripts/start-sysprops-mcp.js +0 -43
- package/scripts/sync-snow-code-version.js +0 -74
- package/scripts/test-auth-flow.js +0 -172
- package/scripts/test-auth-location-fix.js +0 -84
- package/scripts/test-mcp-manual.js +0 -140
- package/scripts/test-todowrite-timeout.js +0 -108
- package/scripts/update-dependencies.js +0 -90
- package/scripts/update-mcp-config.js +0 -96
- package/scripts/update-snow-code.js +0 -146
- package/scripts/verify-snowcode-fork.sh +0 -141
- package/templates/snow-code-package.json +0 -3
package/scripts/diagnose-mcp.js
DELETED
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* MCP Diagnostic Tool - Verifies SnowCode MCP configuration and server startup
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
var fs = require('fs');
|
|
8
|
-
var path = require('path');
|
|
9
|
-
var { execSync } = require('child_process');
|
|
10
|
-
var os = require('os');
|
|
11
|
-
|
|
12
|
-
console.log('\nš SnowCode MCP Diagnostic Tool\n');
|
|
13
|
-
console.log('='.repeat(80));
|
|
14
|
-
|
|
15
|
-
var issues = [];
|
|
16
|
-
var warnings = [];
|
|
17
|
-
var successes = [];
|
|
18
|
-
|
|
19
|
-
// 1. Check SnowCode installation
|
|
20
|
-
console.log('\n1ļøā£ Checking SnowCode installation...');
|
|
21
|
-
try {
|
|
22
|
-
var snowcodeVersion = execSync('snow-code --version 2>&1', { encoding: 'utf-8' }).trim();
|
|
23
|
-
if (snowcodeVersion.includes('command not found')) {
|
|
24
|
-
issues.push('SnowCode CLI not found - install with: npm install -g @groeimetai/snow-code');
|
|
25
|
-
} else {
|
|
26
|
-
successes.push('SnowCode installed: ' + snowcodeVersion);
|
|
27
|
-
console.log(' ā
' + snowcodeVersion);
|
|
28
|
-
}
|
|
29
|
-
} catch (e) {
|
|
30
|
-
issues.push('SnowCode not installed or not in PATH');
|
|
31
|
-
console.log(' ā SnowCode not found');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// 2. Check global snowcode.json
|
|
35
|
-
console.log('\n2ļøā£ Checking global SnowCode configuration...');
|
|
36
|
-
var globalConfigPath = path.join(os.homedir(), '.snowcode', 'snowcode.json');
|
|
37
|
-
if (fs.existsSync(globalConfigPath)) {
|
|
38
|
-
try {
|
|
39
|
-
var globalConfig = JSON.parse(fs.readFileSync(globalConfigPath, 'utf-8'));
|
|
40
|
-
successes.push('Global config exists: ' + globalConfigPath);
|
|
41
|
-
console.log(' ā
Config file found: ' + globalConfigPath);
|
|
42
|
-
|
|
43
|
-
// Check MCP section
|
|
44
|
-
if (globalConfig.mcp) {
|
|
45
|
-
var serverCount = Object.keys(globalConfig.mcp).length;
|
|
46
|
-
successes.push('MCP servers configured: ' + serverCount);
|
|
47
|
-
console.log(' ā
MCP servers configured: ' + serverCount);
|
|
48
|
-
|
|
49
|
-
// List servers
|
|
50
|
-
for (var serverName in globalConfig.mcp) {
|
|
51
|
-
var server = globalConfig.mcp[serverName];
|
|
52
|
-
console.log(' - ' + serverName + ' (type: ' + server.type + ', enabled: ' + server.enabled + ')');
|
|
53
|
-
|
|
54
|
-
// Validate server config
|
|
55
|
-
if (server.type === 'local') {
|
|
56
|
-
// Check command exists
|
|
57
|
-
if (server.command && server.command.length > 0) {
|
|
58
|
-
var scriptPath = server.command[server.command.length - 1]; // Last arg is usually the script
|
|
59
|
-
if (fs.existsSync(scriptPath)) {
|
|
60
|
-
successes.push(serverName + ' script exists: ' + scriptPath);
|
|
61
|
-
console.log(' ā
Script exists: ' + scriptPath);
|
|
62
|
-
} else {
|
|
63
|
-
issues.push(serverName + ' script NOT found: ' + scriptPath);
|
|
64
|
-
console.log(' ā Script NOT found: ' + scriptPath);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Check environment variables
|
|
68
|
-
if (server.environment) {
|
|
69
|
-
var emptyVars = [];
|
|
70
|
-
for (var key in server.environment) {
|
|
71
|
-
var value = server.environment[key];
|
|
72
|
-
if (!value || value === '' || value === '${' + key + '}') {
|
|
73
|
-
emptyVars.push(key);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (emptyVars.length > 0) {
|
|
77
|
-
warnings.push(serverName + ' has empty env vars: ' + emptyVars.join(', '));
|
|
78
|
-
console.log(' ā ļø Empty env vars: ' + emptyVars.join(', '));
|
|
79
|
-
} else {
|
|
80
|
-
successes.push(serverName + ' environment variables configured');
|
|
81
|
-
console.log(' ā
Environment variables configured');
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
} else if (server.type === 'remote') {
|
|
86
|
-
// Check URL and headers
|
|
87
|
-
if (server.url) {
|
|
88
|
-
console.log(' ā
Remote URL: ' + server.url);
|
|
89
|
-
}
|
|
90
|
-
if (server.headers && server.headers.Authorization) {
|
|
91
|
-
var authHeader = server.headers.Authorization;
|
|
92
|
-
if (authHeader === 'Bearer ' || authHeader === 'Bearer') {
|
|
93
|
-
warnings.push(serverName + ' has empty Authorization token');
|
|
94
|
-
console.log(' ā ļø Authorization token is empty (server disabled)');
|
|
95
|
-
} else {
|
|
96
|
-
console.log(' ā
Authorization configured');
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
issues.push('No MCP servers configured in global config');
|
|
103
|
-
console.log(' ā No MCP section found in config');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Validate schema
|
|
107
|
-
if (globalConfig.$schema !== 'https://opencode.ai/config.json') {
|
|
108
|
-
warnings.push('Schema URL mismatch: ' + globalConfig.$schema);
|
|
109
|
-
console.log(' ā ļø Schema: ' + (globalConfig.$schema || 'NOT SET'));
|
|
110
|
-
}
|
|
111
|
-
} catch (e) {
|
|
112
|
-
issues.push('Failed to parse global config: ' + e.message);
|
|
113
|
-
console.log(' ā Failed to parse config: ' + e.message);
|
|
114
|
-
}
|
|
115
|
-
} else {
|
|
116
|
-
issues.push('Global SnowCode config not found: ' + globalConfigPath);
|
|
117
|
-
console.log(' ā Config file not found: ' + globalConfigPath);
|
|
118
|
-
console.log(' š” Run: snow-flow auth login');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// 3. Check local project config
|
|
122
|
-
console.log('\n3ļøā£ Checking local project configuration...');
|
|
123
|
-
var localConfigPath = path.join(process.cwd(), '.snowcode', 'snowcode.json');
|
|
124
|
-
if (fs.existsSync(localConfigPath)) {
|
|
125
|
-
console.log(' ā
Local config exists: ' + localConfigPath);
|
|
126
|
-
console.log(' š” Local config takes priority over global config');
|
|
127
|
-
successes.push('Local project config found (takes priority)');
|
|
128
|
-
} else {
|
|
129
|
-
console.log(' ā¹ļø No local config (using global config)');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 4. Test MCP server startup
|
|
133
|
-
console.log('\n4ļøā£ Testing MCP server startup...');
|
|
134
|
-
if (globalConfig && globalConfig.mcp && globalConfig.mcp['servicenow-unified']) {
|
|
135
|
-
var unifiedServer = globalConfig.mcp['servicenow-unified'];
|
|
136
|
-
if (unifiedServer.type === 'local' && unifiedServer.command) {
|
|
137
|
-
var scriptPath = unifiedServer.command[unifiedServer.command.length - 1];
|
|
138
|
-
console.log(' š§Ŗ Testing servicenow-unified server startup...');
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
// Try to start the server with a timeout
|
|
142
|
-
var testEnv = Object.assign({}, process.env);
|
|
143
|
-
if (unifiedServer.environment) {
|
|
144
|
-
Object.assign(testEnv, unifiedServer.environment);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Start server and kill after 2 seconds
|
|
148
|
-
console.log(' ā³ Starting server (2 second timeout)...');
|
|
149
|
-
var nodeCmd = unifiedServer.command[0];
|
|
150
|
-
var serverArgs = unifiedServer.command.slice(1).join(' ');
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
execSync('timeout 2 ' + nodeCmd + ' ' + serverArgs + ' 2>&1 || true', {
|
|
154
|
-
encoding: 'utf-8',
|
|
155
|
-
env: testEnv,
|
|
156
|
-
timeout: 3000
|
|
157
|
-
});
|
|
158
|
-
console.log(' ā
Server started successfully (no immediate errors)');
|
|
159
|
-
successes.push('MCP server startup test passed');
|
|
160
|
-
} catch (e) {
|
|
161
|
-
if (e.message.includes('timeout')) {
|
|
162
|
-
console.log(' ā
Server running (killed after 2s)');
|
|
163
|
-
successes.push('MCP server startup test passed');
|
|
164
|
-
} else {
|
|
165
|
-
console.log(' ā Server startup failed:');
|
|
166
|
-
console.log(' ' + e.message);
|
|
167
|
-
issues.push('MCP server fails to start: ' + e.message);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
} catch (e) {
|
|
171
|
-
console.log(' ā ļø Could not test server startup: ' + e.message);
|
|
172
|
-
warnings.push('MCP server startup test skipped: ' + e.message);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// 5. Check Snow-Flow version
|
|
178
|
-
console.log('\n5ļøā£ Checking Snow-Flow version...');
|
|
179
|
-
try {
|
|
180
|
-
var snowFlowVersion = execSync('snow-flow --version 2>&1', { encoding: 'utf-8' }).trim();
|
|
181
|
-
console.log(' ā
' + snowFlowVersion);
|
|
182
|
-
successes.push('Snow-Flow installed: ' + snowFlowVersion);
|
|
183
|
-
|
|
184
|
-
// Check if it's the latest version
|
|
185
|
-
if (snowFlowVersion !== '8.6.38') {
|
|
186
|
-
warnings.push('Snow-Flow version mismatch (installed: ' + snowFlowVersion + ', latest: 8.6.38)');
|
|
187
|
-
console.log(' ā ļø Not the latest version (8.6.38)');
|
|
188
|
-
console.log(' š” Update with: npm install -g snow-flow@latest');
|
|
189
|
-
}
|
|
190
|
-
} catch (e) {
|
|
191
|
-
issues.push('Snow-Flow not installed');
|
|
192
|
-
console.log(' ā Snow-Flow not found');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// 6. Check for running MCP processes
|
|
196
|
-
console.log('\n6ļøā£ Checking for running MCP processes...');
|
|
197
|
-
try {
|
|
198
|
-
var processes = execSync('ps aux | grep -i "servicenow-mcp\\|snow-flow-mcp" | grep -v grep || echo "No MCP processes"', {
|
|
199
|
-
encoding: 'utf-8'
|
|
200
|
-
}).trim();
|
|
201
|
-
|
|
202
|
-
if (processes === 'No MCP processes') {
|
|
203
|
-
warnings.push('No MCP server processes currently running');
|
|
204
|
-
console.log(' ā ļø No MCP server processes found');
|
|
205
|
-
console.log(' š” SnowCode should start these automatically when launched');
|
|
206
|
-
} else {
|
|
207
|
-
console.log(' ā
MCP processes running:');
|
|
208
|
-
var lines = processes.split('\n');
|
|
209
|
-
for (var i = 0; i < lines.length; i++) {
|
|
210
|
-
console.log(' ' + lines[i]);
|
|
211
|
-
}
|
|
212
|
-
successes.push('MCP server processes running');
|
|
213
|
-
}
|
|
214
|
-
} catch (e) {
|
|
215
|
-
console.log(' ā¹ļø Could not check processes');
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Summary
|
|
219
|
-
console.log('\n' + '='.repeat(80));
|
|
220
|
-
console.log('š DIAGNOSTIC SUMMARY\n');
|
|
221
|
-
|
|
222
|
-
if (successes.length > 0) {
|
|
223
|
-
console.log('ā
SUCCESSES (' + successes.length + '):');
|
|
224
|
-
for (var i = 0; i < successes.length; i++) {
|
|
225
|
-
console.log(' ā ' + successes[i]);
|
|
226
|
-
}
|
|
227
|
-
console.log('');
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (warnings.length > 0) {
|
|
231
|
-
console.log('ā ļø WARNINGS (' + warnings.length + '):');
|
|
232
|
-
for (var i = 0; i < warnings.length; i++) {
|
|
233
|
-
console.log(' ā ' + warnings[i]);
|
|
234
|
-
}
|
|
235
|
-
console.log('');
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (issues.length > 0) {
|
|
239
|
-
console.log('ā ISSUES (' + issues.length + '):');
|
|
240
|
-
for (var i = 0; i < issues.length; i++) {
|
|
241
|
-
console.log(' ā ' + issues[i]);
|
|
242
|
-
}
|
|
243
|
-
console.log('');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Recommendations
|
|
247
|
-
console.log('š” RECOMMENDATIONS:\n');
|
|
248
|
-
|
|
249
|
-
if (issues.length > 0) {
|
|
250
|
-
console.log('1. Fix the issues above first:');
|
|
251
|
-
if (issues.some(function(i) { return i.includes('SnowCode not installed'); })) {
|
|
252
|
-
console.log(' ā Install SnowCode: npm install -g @groeimetai/snow-code');
|
|
253
|
-
}
|
|
254
|
-
if (issues.some(function(i) { return i.includes('config not found'); })) {
|
|
255
|
-
console.log(' ā Configure Snow-Flow: snow-flow auth login');
|
|
256
|
-
}
|
|
257
|
-
if (issues.some(function(i) { return i.includes('script NOT found'); })) {
|
|
258
|
-
console.log(' ā Reinstall Snow-Flow: npm install -g snow-flow@latest');
|
|
259
|
-
}
|
|
260
|
-
if (issues.some(function(i) { return i.includes('server fails to start'); })) {
|
|
261
|
-
console.log(' ā Check MCP server logs for errors');
|
|
262
|
-
console.log(' ā Verify credentials in snowcode.json are correct');
|
|
263
|
-
}
|
|
264
|
-
console.log('');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (warnings.length > 0 && issues.length === 0) {
|
|
268
|
-
console.log('2. Address warnings:');
|
|
269
|
-
if (warnings.some(function(w) { return w.includes('empty env vars'); })) {
|
|
270
|
-
console.log(' ā Run: snow-flow auth login (to set credentials)');
|
|
271
|
-
}
|
|
272
|
-
if (warnings.some(function(w) { return w.includes('version mismatch'); })) {
|
|
273
|
-
console.log(' ā Update: npm install -g snow-flow@latest');
|
|
274
|
-
}
|
|
275
|
-
if (warnings.some(function(w) { return w.includes('No MCP processes'); })) {
|
|
276
|
-
console.log(' ā SnowCode should auto-start MCP servers');
|
|
277
|
-
console.log(' ā If tools still unavailable, restart SnowCode completely');
|
|
278
|
-
}
|
|
279
|
-
console.log('');
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (issues.length === 0 && warnings.length === 0) {
|
|
283
|
-
console.log('ā
Configuration looks good!');
|
|
284
|
-
console.log('');
|
|
285
|
-
console.log('If MCP tools are still not available in SnowCode:');
|
|
286
|
-
console.log('1. Completely quit SnowCode (not just close window)');
|
|
287
|
-
console.log('2. Restart SnowCode: snow-code');
|
|
288
|
-
console.log('3. Tools should be available immediately');
|
|
289
|
-
console.log('');
|
|
290
|
-
console.log('Test MCP tools with:');
|
|
291
|
-
console.log(' await snow_query_table({ table: "sys_user", limit: 1 })');
|
|
292
|
-
console.log('');
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
console.log('š Next steps if issues persist:');
|
|
296
|
-
console.log(' 1. Check SnowCode logs for MCP startup errors');
|
|
297
|
-
console.log(' 2. Verify SnowCode is reading ~/.snowcode/snowcode.json');
|
|
298
|
-
console.log(' 3. Try manual MCP server test: node ' + (globalConfig && globalConfig.mcp && globalConfig.mcp['servicenow-unified'] ? globalConfig.mcp['servicenow-unified'].command[1] : '[path-to-mcp-server]'));
|
|
299
|
-
console.log('');
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const dotenv = require('dotenv');
|
|
6
|
-
|
|
7
|
-
// Load environment variables
|
|
8
|
-
const envPath = path.join(__dirname, '..', '.env');
|
|
9
|
-
if (fs.existsSync(envPath)) {
|
|
10
|
-
dotenv.config({ path: envPath });
|
|
11
|
-
} else {
|
|
12
|
-
console.error('ā .env file not found!');
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Read template
|
|
17
|
-
const templatePath = path.join(__dirname, '..', '.mcp.json.template');
|
|
18
|
-
const template = JSON.parse(fs.readFileSync(templatePath, 'utf-8'));
|
|
19
|
-
|
|
20
|
-
// Process template - replace variables
|
|
21
|
-
const config = JSON.parse(JSON.stringify(template)
|
|
22
|
-
.replace(/{{PROJECT_ROOT}}/g, path.resolve(__dirname, '..'))
|
|
23
|
-
.replace(/{{SNOW_INSTANCE}}/g, process.env.SNOW_INSTANCE || '')
|
|
24
|
-
.replace(/{{SNOW_CLIENT_ID}}/g, process.env.SNOW_CLIENT_ID || '')
|
|
25
|
-
.replace(/{{SNOW_CLIENT_SECRET}}/g, process.env.SNOW_CLIENT_SECRET || '')
|
|
26
|
-
.replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, process.env.SNOW_DEPLOYMENT_TIMEOUT || '300000')
|
|
27
|
-
.replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, process.env.MCP_DEPLOYMENT_TIMEOUT || '360000')
|
|
28
|
-
.replace(/{{SNOW_FLOW_ENV}}/g, process.env.SNOW_FLOW_ENV || 'production')
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
// Write config
|
|
32
|
-
const outputPath = path.join(__dirname, '..', '.mcp.json');
|
|
33
|
-
fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));
|
|
34
|
-
|
|
35
|
-
console.log('ā
Generated .mcp.json with all ServiceNow MCP servers');
|
|
36
|
-
console.log(`š Location: ${outputPath}`);
|
|
37
|
-
console.log(`š§ Servers configured: ${Object.keys(config.servers).length}`);
|
|
38
|
-
console.log('\nServers:');
|
|
39
|
-
Object.keys(config.servers).forEach(server => {
|
|
40
|
-
console.log(` ā ${server}`);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
console.log('\nš” Next steps:');
|
|
44
|
-
console.log('1. Restart Claude Code to load the new configuration');
|
|
45
|
-
console.log('2. Run /doctor again to verify everything is working');
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# MCP Server Manager for Snow-Flow
|
|
4
|
-
# Helps start, stop, and monitor MCP servers for OpenCode
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
set -e
|
|
8
|
-
|
|
9
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
-
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
11
|
-
MCP_SERVER_PATH="$PROJECT_ROOT/dist/mcp/servicenow-mcp-unified/index.js"
|
|
12
|
-
PID_FILE="/tmp/snow-flow-mcp.pid"
|
|
13
|
-
LOG_FILE="/tmp/snow-flow-mcp.log"
|
|
14
|
-
|
|
15
|
-
# Colors
|
|
16
|
-
RED='\033[0;31m'
|
|
17
|
-
GREEN='\033[0;32m'
|
|
18
|
-
YELLOW='\033[1;33m'
|
|
19
|
-
BLUE='\033[0;34m'
|
|
20
|
-
NC='\033[0m' # No Color
|
|
21
|
-
|
|
22
|
-
# Load .env file if exists
|
|
23
|
-
load_env() {
|
|
24
|
-
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|
25
|
-
echo -e "${BLUE}Loading environment from .env...${NC}"
|
|
26
|
-
export $(cat "$PROJECT_ROOT/.env" | grep -v '^#' | grep -v '^$' | xargs)
|
|
27
|
-
else
|
|
28
|
-
echo -e "${YELLOW}Warning: No .env file found${NC}"
|
|
29
|
-
echo "Please create one from .env.example:"
|
|
30
|
-
echo " cp .env.example .env"
|
|
31
|
-
echo " # Then edit .env with your credentials"
|
|
32
|
-
exit 1
|
|
33
|
-
fi
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
# Check if MCP server is built
|
|
37
|
-
check_build() {
|
|
38
|
-
if [ ! -f "$MCP_SERVER_PATH" ]; then
|
|
39
|
-
echo -e "${RED}Error: MCP server not built!${NC}"
|
|
40
|
-
echo "Run: npm run build"
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
echo -e "${GREEN}ā MCP server binary found${NC}"
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
# Check if MCP server is running
|
|
47
|
-
is_running() {
|
|
48
|
-
if [ -f "$PID_FILE" ]; then
|
|
49
|
-
PID=$(cat "$PID_FILE")
|
|
50
|
-
if ps -p "$PID" > /dev/null 2>&1; then
|
|
51
|
-
return 0
|
|
52
|
-
else
|
|
53
|
-
rm -f "$PID_FILE"
|
|
54
|
-
return 1
|
|
55
|
-
fi
|
|
56
|
-
fi
|
|
57
|
-
return 1
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
# Start MCP server
|
|
61
|
-
start_server() {
|
|
62
|
-
echo -e "${BLUE}Starting MCP server...${NC}"
|
|
63
|
-
|
|
64
|
-
load_env
|
|
65
|
-
check_build
|
|
66
|
-
|
|
67
|
-
if is_running; then
|
|
68
|
-
echo -e "${YELLOW}MCP server is already running (PID: $(cat $PID_FILE))${NC}"
|
|
69
|
-
return 0
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
# Prepare environment variables
|
|
73
|
-
export SERVICENOW_INSTANCE_URL="https://${SNOW_INSTANCE}"
|
|
74
|
-
|
|
75
|
-
# Try OAuth first, fall back to username/password
|
|
76
|
-
if [ -n "$SNOW_CLIENT_ID" ] && [ -n "$SNOW_CLIENT_SECRET" ]; then
|
|
77
|
-
echo -e "${GREEN}Using OAuth authentication${NC}"
|
|
78
|
-
export SERVICENOW_CLIENT_ID="$SNOW_CLIENT_ID"
|
|
79
|
-
export SERVICENOW_CLIENT_SECRET="$SNOW_CLIENT_SECRET"
|
|
80
|
-
elif [ -n "$SNOW_USERNAME" ] && [ -n "$SNOW_PASSWORD" ]; then
|
|
81
|
-
echo -e "${GREEN}Using Username/Password authentication${NC}"
|
|
82
|
-
export SERVICENOW_USERNAME="$SNOW_USERNAME"
|
|
83
|
-
export SERVICENOW_PASSWORD="$SNOW_PASSWORD"
|
|
84
|
-
else
|
|
85
|
-
echo -e "${RED}Error: No authentication credentials found!${NC}"
|
|
86
|
-
echo "Set either:"
|
|
87
|
-
echo " - SNOW_CLIENT_ID + SNOW_CLIENT_SECRET (OAuth)"
|
|
88
|
-
echo " - SNOW_USERNAME + SNOW_PASSWORD"
|
|
89
|
-
exit 1
|
|
90
|
-
fi
|
|
91
|
-
|
|
92
|
-
# Start server in background
|
|
93
|
-
nohup node "$MCP_SERVER_PATH" > "$LOG_FILE" 2>&1 &
|
|
94
|
-
PID=$!
|
|
95
|
-
echo $PID > "$PID_FILE"
|
|
96
|
-
|
|
97
|
-
# Wait for server to start
|
|
98
|
-
echo -e "${BLUE}Waiting for server to start...${NC}"
|
|
99
|
-
sleep 2
|
|
100
|
-
|
|
101
|
-
if is_running; then
|
|
102
|
-
echo -e "${GREEN}ā MCP server started (PID: $PID)${NC}"
|
|
103
|
-
echo -e "${BLUE}Log file: $LOG_FILE${NC}"
|
|
104
|
-
return 0
|
|
105
|
-
else
|
|
106
|
-
echo -e "${RED}ā Failed to start MCP server${NC}"
|
|
107
|
-
echo "Check logs: cat $LOG_FILE"
|
|
108
|
-
return 1
|
|
109
|
-
fi
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
# Stop MCP server
|
|
113
|
-
stop_server() {
|
|
114
|
-
echo -e "${BLUE}Stopping MCP server...${NC}"
|
|
115
|
-
|
|
116
|
-
if ! is_running; then
|
|
117
|
-
echo -e "${YELLOW}MCP server is not running${NC}"
|
|
118
|
-
return 0
|
|
119
|
-
fi
|
|
120
|
-
|
|
121
|
-
PID=$(cat "$PID_FILE")
|
|
122
|
-
kill $PID 2>/dev/null || true
|
|
123
|
-
sleep 1
|
|
124
|
-
|
|
125
|
-
if ! is_running; then
|
|
126
|
-
echo -e "${GREEN}ā MCP server stopped${NC}"
|
|
127
|
-
rm -f "$PID_FILE"
|
|
128
|
-
else
|
|
129
|
-
echo -e "${YELLOW}Forcing server shutdown...${NC}"
|
|
130
|
-
kill -9 $PID 2>/dev/null || true
|
|
131
|
-
rm -f "$PID_FILE"
|
|
132
|
-
echo -e "${GREEN}ā MCP server killed${NC}"
|
|
133
|
-
fi
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
# Check MCP server status
|
|
137
|
-
status_check() {
|
|
138
|
-
echo -e "${BLUE}Checking MCP server status...${NC}"
|
|
139
|
-
|
|
140
|
-
check_build
|
|
141
|
-
|
|
142
|
-
if is_running; then
|
|
143
|
-
PID=$(cat "$PID_FILE")
|
|
144
|
-
echo -e "${GREEN}ā MCP server is running (PID: $PID)${NC}"
|
|
145
|
-
|
|
146
|
-
# Check tool count
|
|
147
|
-
TOOL_COUNT=$(grep -c "Registered:" "$LOG_FILE" 2>/dev/null || echo "0")
|
|
148
|
-
echo -e "${GREEN}ā Tools loaded: $TOOL_COUNT${NC}"
|
|
149
|
-
|
|
150
|
-
# Check last 10 log lines
|
|
151
|
-
echo -e "\n${BLUE}Recent logs:${NC}"
|
|
152
|
-
tail -n 10 "$LOG_FILE" 2>/dev/null || echo "No logs available"
|
|
153
|
-
|
|
154
|
-
return 0
|
|
155
|
-
else
|
|
156
|
-
echo -e "${RED}ā MCP server is not running${NC}"
|
|
157
|
-
return 1
|
|
158
|
-
fi
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
# Health check with tool test
|
|
162
|
-
health_check() {
|
|
163
|
-
echo -e "${BLUE}Running health check...${NC}"
|
|
164
|
-
|
|
165
|
-
if ! is_running; then
|
|
166
|
-
echo -e "${RED}ā MCP server is not running${NC}"
|
|
167
|
-
echo "Start it with: $0 start"
|
|
168
|
-
return 1
|
|
169
|
-
fi
|
|
170
|
-
|
|
171
|
-
load_env
|
|
172
|
-
|
|
173
|
-
# Test JSON-RPC communication
|
|
174
|
-
echo -e "${BLUE}Testing JSON-RPC communication...${NC}"
|
|
175
|
-
|
|
176
|
-
cat > /tmp/mcp_health_check.js << 'EOF'
|
|
177
|
-
const { spawn } = require('child_process');
|
|
178
|
-
|
|
179
|
-
const mcp = spawn('node', [process.argv[2]], {
|
|
180
|
-
env: process.env,
|
|
181
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
let buffer = '';
|
|
185
|
-
let testPassed = false;
|
|
186
|
-
|
|
187
|
-
mcp.stdout.on('data', (data) => {
|
|
188
|
-
buffer += data.toString();
|
|
189
|
-
const lines = buffer.split('\n');
|
|
190
|
-
buffer = lines.pop();
|
|
191
|
-
|
|
192
|
-
lines.forEach(line => {
|
|
193
|
-
if (line.trim() && line.startsWith('{')) {
|
|
194
|
-
try {
|
|
195
|
-
const msg = JSON.parse(line);
|
|
196
|
-
if (msg.result && msg.result.tools) {
|
|
197
|
-
console.log(`ā Health check passed - ${msg.result.tools.length} tools available`);
|
|
198
|
-
testPassed = true;
|
|
199
|
-
mcp.kill();
|
|
200
|
-
process.exit(0);
|
|
201
|
-
}
|
|
202
|
-
} catch (e) {}
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
mcp.stderr.on('data', (data) => {
|
|
208
|
-
// Ignore stderr logs from server
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Initialize and list tools
|
|
212
|
-
setTimeout(() => {
|
|
213
|
-
const initRequest = {
|
|
214
|
-
jsonrpc: '2.0',
|
|
215
|
-
id: 1,
|
|
216
|
-
method: 'initialize',
|
|
217
|
-
params: {
|
|
218
|
-
protocolVersion: '2024-11-05',
|
|
219
|
-
capabilities: {},
|
|
220
|
-
clientInfo: { name: 'health-check', version: '1.0.0' }
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
mcp.stdin.write(JSON.stringify(initRequest) + '\n');
|
|
224
|
-
}, 500);
|
|
225
|
-
|
|
226
|
-
setTimeout(() => {
|
|
227
|
-
const toolsRequest = {
|
|
228
|
-
jsonrpc: '2.0',
|
|
229
|
-
id: 2,
|
|
230
|
-
method: 'tools/list'
|
|
231
|
-
};
|
|
232
|
-
mcp.stdin.write(JSON.stringify(toolsRequest) + '\n');
|
|
233
|
-
}, 1500);
|
|
234
|
-
|
|
235
|
-
setTimeout(() => {
|
|
236
|
-
if (!testPassed) {
|
|
237
|
-
console.log('ā Health check failed - timeout');
|
|
238
|
-
mcp.kill();
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
}, 5000);
|
|
242
|
-
EOF
|
|
243
|
-
|
|
244
|
-
SERVICENOW_INSTANCE_URL="https://${SNOW_INSTANCE}" \
|
|
245
|
-
SERVICENOW_CLIENT_ID="$SNOW_CLIENT_ID" \
|
|
246
|
-
SERVICENOW_CLIENT_SECRET="$SNOW_CLIENT_SECRET" \
|
|
247
|
-
SERVICENOW_USERNAME="$SNOW_USERNAME" \
|
|
248
|
-
SERVICENOW_PASSWORD="$SNOW_PASSWORD" \
|
|
249
|
-
node /tmp/mcp_health_check.js "$MCP_SERVER_PATH"
|
|
250
|
-
|
|
251
|
-
rm -f /tmp/mcp_health_check.js
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
# Show logs
|
|
255
|
-
show_logs() {
|
|
256
|
-
if [ -f "$LOG_FILE" ]; then
|
|
257
|
-
echo -e "${BLUE}MCP Server Logs:${NC}"
|
|
258
|
-
tail -f "$LOG_FILE"
|
|
259
|
-
else
|
|
260
|
-
echo -e "${YELLOW}No logs available${NC}"
|
|
261
|
-
fi
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
# Restart server
|
|
265
|
-
restart_server() {
|
|
266
|
-
stop_server
|
|
267
|
-
sleep 1
|
|
268
|
-
start_server
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
# Main menu
|
|
272
|
-
show_help() {
|
|
273
|
-
echo "MCP Server Manager for Snow-Flow"
|
|
274
|
-
echo ""
|
|
275
|
-
echo "Usage: $0 [command]"
|
|
276
|
-
echo ""
|
|
277
|
-
echo "Commands:"
|
|
278
|
-
echo " start Start MCP server"
|
|
279
|
-
echo " stop Stop MCP server"
|
|
280
|
-
echo " restart Restart MCP server"
|
|
281
|
-
echo " status Show server status"
|
|
282
|
-
echo " health Run health check"
|
|
283
|
-
echo " logs Show server logs (live)"
|
|
284
|
-
echo " help Show this help"
|
|
285
|
-
echo ""
|
|
286
|
-
echo "Examples:"
|
|
287
|
-
echo " $0 start # Start MCP server in background"
|
|
288
|
-
echo " $0 health # Test JSON-RPC communication"
|
|
289
|
-
echo " $0 logs # Follow server logs"
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
# Parse command
|
|
293
|
-
case "${1:-help}" in
|
|
294
|
-
start)
|
|
295
|
-
start_server
|
|
296
|
-
;;
|
|
297
|
-
stop)
|
|
298
|
-
stop_server
|
|
299
|
-
;;
|
|
300
|
-
restart)
|
|
301
|
-
restart_server
|
|
302
|
-
;;
|
|
303
|
-
status)
|
|
304
|
-
status_check
|
|
305
|
-
;;
|
|
306
|
-
health)
|
|
307
|
-
health_check
|
|
308
|
-
;;
|
|
309
|
-
logs)
|
|
310
|
-
show_logs
|
|
311
|
-
;;
|
|
312
|
-
help|--help|-h)
|
|
313
|
-
show_help
|
|
314
|
-
;;
|
|
315
|
-
*)
|
|
316
|
-
echo -e "${RED}Unknown command: $1${NC}"
|
|
317
|
-
show_help
|
|
318
|
-
exit 1
|
|
319
|
-
;;
|
|
320
|
-
esac
|