snow-flow 3.4.39 → 3.5.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.
@@ -0,0 +1,570 @@
1
+ "use strict";
2
+ /**
3
+ * ServiceNow Local Development MCP Server
4
+ *
5
+ * Bridges ServiceNow artifacts with Claude Code's native file tools
6
+ * by creating temporary local files that can be edited with full
7
+ * Claude Code capabilities, then synced back to ServiceNow.
8
+ *
9
+ * THIS IS THE KEY TO POWERFUL SERVICENOW DEVELOPMENT!
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.ServiceNowLocalDevelopmentMCP = void 0;
46
+ const base_mcp_server_1 = require("./base-mcp-server");
47
+ const artifact_local_sync_1 = require("../utils/artifact-local-sync");
48
+ const artifact_registry_1 = require("../utils/artifact-sync/artifact-registry");
49
+ const fs = __importStar(require("fs"));
50
+ class ServiceNowLocalDevelopmentMCP extends base_mcp_server_1.BaseMCPServer {
51
+ constructor() {
52
+ super('servicenow-local-development', '1.0.0');
53
+ this.syncManager = new artifact_local_sync_1.ArtifactLocalSync(this.serviceNowClient);
54
+ }
55
+ async initializeTools() {
56
+ // DYNAMIC pull tool - works with ALL artifact types!
57
+ this.addTool({
58
+ name: 'snow_pull_artifact',
59
+ description: `Pull ANY ServiceNow artifact to local files for editing with Claude Code's native tools.
60
+ Automatically detects the artifact type and creates appropriate files based on the artifact registry.
61
+ Supports: ${(0, artifact_registry_1.getSupportedTables)().map(t => (0, artifact_registry_1.getTableDisplayName)(t)).join(', ')}`,
62
+ inputSchema: {
63
+ type: 'object',
64
+ properties: {
65
+ sys_id: {
66
+ type: 'string',
67
+ description: 'Artifact sys_id to pull'
68
+ },
69
+ table: {
70
+ type: 'string',
71
+ description: 'Optional: Specify table name if known',
72
+ enum: (0, artifact_registry_1.getSupportedTables)()
73
+ }
74
+ },
75
+ required: ['sys_id']
76
+ },
77
+ handler: async (args) => this.pullArtifact(args)
78
+ });
79
+ // Keep backward compatibility - widget-specific tool
80
+ this.addTool({
81
+ name: 'snow_pull_widget',
82
+ description: `Pull a ServiceNow widget to local files (legacy - use snow_pull_artifact instead)`,
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ sys_id: {
87
+ type: 'string',
88
+ description: 'Widget sys_id to pull'
89
+ }
90
+ },
91
+ required: ['sys_id']
92
+ },
93
+ handler: async (args) => this.pullArtifact({ ...args, table: 'sp_widget' })
94
+ });
95
+ this.addTool({
96
+ name: 'snow_pull_script_include',
97
+ description: 'Pull a Script Include to local JavaScript file (legacy - use snow_pull_artifact)',
98
+ inputSchema: {
99
+ type: 'object',
100
+ properties: {
101
+ sys_id: {
102
+ type: 'string',
103
+ description: 'Script Include sys_id'
104
+ }
105
+ },
106
+ required: ['sys_id']
107
+ },
108
+ handler: async (args) => this.pullArtifact({ ...args, table: 'sys_script_include' })
109
+ });
110
+ this.addTool({
111
+ name: 'snow_pull_business_rule',
112
+ description: 'Pull a Business Rule to local JavaScript file (legacy - use snow_pull_artifact)',
113
+ inputSchema: {
114
+ type: 'object',
115
+ properties: {
116
+ sys_id: {
117
+ type: 'string',
118
+ description: 'Business Rule sys_id'
119
+ }
120
+ },
121
+ required: ['sys_id']
122
+ },
123
+ handler: async (args) => this.pullArtifact({ ...args, table: 'sys_script' })
124
+ });
125
+ // DYNAMIC push tool - works with ALL artifact types!
126
+ this.addTool({
127
+ name: 'snow_push_artifact',
128
+ description: `Push local artifact changes back to ServiceNow.
129
+ Automatically detects which files changed, validates based on artifact type,
130
+ and updates the corresponding fields. Runs coherence validation for artifacts with rules.`,
131
+ inputSchema: {
132
+ type: 'object',
133
+ properties: {
134
+ sys_id: {
135
+ type: 'string',
136
+ description: 'Artifact sys_id to push changes for'
137
+ },
138
+ force: {
139
+ type: 'boolean',
140
+ description: 'Force push even with validation warnings',
141
+ default: false
142
+ }
143
+ },
144
+ required: ['sys_id']
145
+ },
146
+ handler: async (args) => this.pushArtifact(args)
147
+ });
148
+ // Keep backward compatibility
149
+ this.addTool({
150
+ name: 'snow_push_widget',
151
+ description: `Push local widget changes back to ServiceNow (legacy - use snow_push_artifact)`,
152
+ inputSchema: {
153
+ type: 'object',
154
+ properties: {
155
+ sys_id: {
156
+ type: 'string',
157
+ description: 'Widget sys_id to push'
158
+ }
159
+ },
160
+ required: ['sys_id']
161
+ },
162
+ handler: async (args) => this.pushArtifact(args)
163
+ });
164
+ // Sync status tools
165
+ this.addTool({
166
+ name: 'snow_sync_status',
167
+ description: 'Check sync status of local artifacts - shows what\'s modified',
168
+ inputSchema: {
169
+ type: 'object',
170
+ properties: {
171
+ sys_id: {
172
+ type: 'string',
173
+ description: 'Optional: specific artifact sys_id'
174
+ }
175
+ }
176
+ },
177
+ handler: async (args) => this.getSyncStatus(args)
178
+ });
179
+ this.addTool({
180
+ name: 'snow_sync_cleanup',
181
+ description: 'Clean up local files after successful sync',
182
+ inputSchema: {
183
+ type: 'object',
184
+ properties: {
185
+ sys_id: {
186
+ type: 'string',
187
+ description: 'Artifact sys_id to clean up'
188
+ },
189
+ force: {
190
+ type: 'boolean',
191
+ description: 'Force cleanup even with unsaved changes',
192
+ default: false
193
+ }
194
+ },
195
+ required: ['sys_id']
196
+ },
197
+ handler: async (args) => this.cleanup(args)
198
+ });
199
+ // List supported artifact types
200
+ this.addTool({
201
+ name: 'snow_list_supported_artifacts',
202
+ description: 'List all artifact types supported by the local sync system',
203
+ inputSchema: {
204
+ type: 'object',
205
+ properties: {}
206
+ },
207
+ handler: async () => this.listSupportedArtifacts()
208
+ });
209
+ this.addTool({
210
+ name: 'snow_validate_artifact_coherence',
211
+ description: 'Validate artifact based on its type-specific coherence rules',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {
215
+ sys_id: {
216
+ type: 'string',
217
+ description: 'Artifact sys_id to validate'
218
+ }
219
+ },
220
+ required: ['sys_id']
221
+ },
222
+ handler: async (args) => this.validateCoherence(args)
223
+ });
224
+ this.addTool({
225
+ name: 'snow_convert_to_es5',
226
+ description: 'Convert modern JavaScript to ES5 for ServiceNow compatibility',
227
+ inputSchema: {
228
+ type: 'object',
229
+ properties: {
230
+ file_path: {
231
+ type: 'string',
232
+ description: 'Path to JavaScript file to convert'
233
+ },
234
+ inline_code: {
235
+ type: 'string',
236
+ description: 'Or provide code directly'
237
+ }
238
+ }
239
+ },
240
+ handler: async (args) => this.convertToES5(args)
241
+ });
242
+ // Search tools that work like Claude Code
243
+ this.addTool({
244
+ name: 'snow_search_in_widgets',
245
+ description: 'Search across all widget fields (like Claude Code search but for ServiceNow)',
246
+ inputSchema: {
247
+ type: 'object',
248
+ properties: {
249
+ search_term: {
250
+ type: 'string',
251
+ description: 'Text to search for'
252
+ },
253
+ field: {
254
+ type: 'string',
255
+ description: 'Specific field to search in',
256
+ enum: ['template', 'script', 'client_script', 'css', 'all']
257
+ },
258
+ regex: {
259
+ type: 'boolean',
260
+ description: 'Use regex search',
261
+ default: false
262
+ }
263
+ },
264
+ required: ['search_term']
265
+ },
266
+ handler: async (args) => this.searchInWidgets(args)
267
+ });
268
+ }
269
+ /**
270
+ * DYNAMIC pull artifact to local files
271
+ */
272
+ async pullArtifact(args) {
273
+ try {
274
+ let artifact;
275
+ if (args.table) {
276
+ // Table specified - direct pull
277
+ artifact = await this.syncManager.pullArtifact(args.table, args.sys_id);
278
+ }
279
+ else {
280
+ // Auto-detect table
281
+ artifact = await this.syncManager.pullArtifactBySysId(args.sys_id);
282
+ }
283
+ const config = artifact.artifactConfig;
284
+ const hasES5 = config?.fieldMappings.some(fm => fm.validateES5);
285
+ const hasCoherence = config?.coherenceRules && config.coherenceRules.length > 0;
286
+ const message = `
287
+ ✅ **${artifact.type} pulled to local files successfully!**
288
+
289
+ 📁 **Location:** \`${artifact.localPath}\`
290
+
291
+ 📄 **Files created:**
292
+ ${artifact.files.map(f => `- **${f.filename}** (${f.type})`).join('\n')}
293
+
294
+ 🎯 **Now you can:**
295
+ 1. Use Claude Code's native tools to edit these files
296
+ 2. Search across files with full regex support
297
+ 3. Multi-file operations and refactoring
298
+ 4. Use all VS Code/editor features
299
+ 5. When done, run \`snow_push_artifact\` to sync back
300
+
301
+ ${hasES5 ? `⚠️ **ES5 Requirement:**
302
+ - Server-side scripts MUST be ES5 only
303
+ - No const/let/arrow functions/template literals
304
+ - Use var and function() syntax only
305
+
306
+ ` : ''}
307
+ ${hasCoherence ? `🔗 **Coherence Rules:**
308
+ - This artifact has validation rules that will be checked
309
+ - Run \`snow_validate_artifact_coherence\` to test
310
+ - Push will warn about any violations
311
+
312
+ ` : ''}
313
+ 📝 **Edit the files now, then push changes back to ServiceNow!**
314
+ `;
315
+ return {
316
+ success: true,
317
+ result: artifact,
318
+ message
319
+ };
320
+ }
321
+ catch (error) {
322
+ return this.error(`Failed to pull artifact: ${error.message}`);
323
+ }
324
+ }
325
+ /**
326
+ * Push artifact changes back to ServiceNow
327
+ */
328
+ async pushArtifact(args) {
329
+ try {
330
+ // First run coherence validation
331
+ const validationResults = await this.syncManager.validateArtifactCoherence(args.sys_id);
332
+ if (validationResults.length > 0 && !args.force) {
333
+ const hasErrors = validationResults.some(r => !r.valid);
334
+ if (hasErrors) {
335
+ const message = `
336
+ ⚠️ **Validation Issues Found**
337
+
338
+ ${validationResults.map(r => {
339
+ let output = '';
340
+ if (r.errors.length > 0) {
341
+ output += '**Errors:**\n' + r.errors.map(e => `- ❌ ${e}`).join('\n') + '\n';
342
+ }
343
+ if (r.warnings.length > 0) {
344
+ output += '**Warnings:**\n' + r.warnings.map(w => `- ⚠️ ${w}`).join('\n') + '\n';
345
+ }
346
+ if (r.hints.length > 0) {
347
+ output += '**Hints:**\n' + r.hints.map(h => `- 💡 ${h}`).join('\n');
348
+ }
349
+ return output;
350
+ }).join('\n\n')}
351
+
352
+ ❓ Use \`force: true\` to push anyway, but this may cause runtime errors.
353
+ `;
354
+ return {
355
+ success: false,
356
+ result: { validationResults },
357
+ message
358
+ };
359
+ }
360
+ }
361
+ const success = await this.syncManager.pushArtifact(args.sys_id);
362
+ if (success) {
363
+ return {
364
+ success: true,
365
+ result: { pushed: true },
366
+ message: `✅ Artifact successfully pushed to ServiceNow! Changes are now live.`
367
+ };
368
+ }
369
+ else {
370
+ return this.error('Failed to push artifact - check logs for details');
371
+ }
372
+ }
373
+ catch (error) {
374
+ return this.error(`Failed to push artifact: ${error.message}`);
375
+ }
376
+ }
377
+ /**
378
+ * Get sync status
379
+ */
380
+ async getSyncStatus(args) {
381
+ const artifacts = this.syncManager.listLocalArtifacts();
382
+ if (args.sys_id) {
383
+ const status = this.syncManager.getSyncStatus(args.sys_id);
384
+ return {
385
+ success: true,
386
+ result: { status },
387
+ message: `Sync status for ${args.sys_id}: ${status}`
388
+ };
389
+ }
390
+ const message = `
391
+ 📊 **Local Artifacts Sync Status**
392
+
393
+ ${artifacts.length === 0 ? '📭 No local artifacts currently synced' : ''}
394
+ ${artifacts.map(a => `
395
+ **${a.name}** (${a.type})
396
+ - sys_id: \`${a.sys_id}\`
397
+ - Status: **${a.syncStatus}**
398
+ - Path: \`${a.localPath}\`
399
+ - Files: ${a.files.length}
400
+ - Modified: ${a.files.filter(f => f.isModified).length}
401
+ - Last sync: ${a.lastSyncedAt.toLocaleString()}
402
+ `).join('\n---\n')}
403
+
404
+ 💡 Use \`snow_push_artifact <sys_id>\` to push changes
405
+ 🧹 Use \`snow_sync_cleanup <sys_id>\` to remove local files
406
+ `;
407
+ return {
408
+ success: true,
409
+ result: artifacts,
410
+ message
411
+ };
412
+ }
413
+ /**
414
+ * Cleanup local files
415
+ */
416
+ async cleanup(args) {
417
+ try {
418
+ await this.syncManager.cleanup(args.sys_id, args.force);
419
+ return {
420
+ success: true,
421
+ result: { cleaned: true },
422
+ message: `✅ Local files cleaned up successfully`
423
+ };
424
+ }
425
+ catch (error) {
426
+ return this.error(`Cleanup failed: ${error.message}`);
427
+ }
428
+ }
429
+ /**
430
+ * List supported artifact types
431
+ */
432
+ async listSupportedArtifacts() {
433
+ const types = (0, artifact_registry_1.getSupportedTables)();
434
+ const details = types.map(table => {
435
+ const config = artifact_registry_1.ARTIFACT_REGISTRY[table];
436
+ return {
437
+ table,
438
+ displayName: config.displayName,
439
+ folderName: config.folderName,
440
+ fields: config.fieldMappings.length,
441
+ hasCoherence: (config.coherenceRules?.length || 0) > 0,
442
+ requiresES5: config.fieldMappings.some(fm => fm.validateES5)
443
+ };
444
+ });
445
+ const message = `
446
+ 📚 **Supported ServiceNow Artifact Types**
447
+
448
+ ${details.map(d => `
449
+ **${d.displayName}**
450
+ - Table: \`${d.table}\`
451
+ - Folder: \`${d.folderName}/\`
452
+ - Fields: ${d.fields}
453
+ - Coherence Rules: ${d.hasCoherence ? '✅' : '❌'}
454
+ - ES5 Required: ${d.requiresES5 ? '⚠️ Yes' : '✅ No'}
455
+ `).join('\n')}
456
+
457
+ 💡 **Usage:**
458
+ \`\`\`
459
+ snow_pull_artifact({ sys_id: 'abc123' }) // Auto-detect type
460
+ snow_pull_artifact({ sys_id: 'abc123', table: 'sp_widget' }) // Specific type
461
+ \`\`\`
462
+ `;
463
+ return {
464
+ success: true,
465
+ result: details,
466
+ message
467
+ };
468
+ }
469
+ /**
470
+ * Validate artifact coherence
471
+ */
472
+ async validateCoherence(args) {
473
+ try {
474
+ const results = await this.syncManager.validateArtifactCoherence(args.sys_id);
475
+ if (results.length === 0) {
476
+ return {
477
+ success: true,
478
+ result: { valid: true },
479
+ message: '✅ No coherence rules defined for this artifact type'
480
+ };
481
+ }
482
+ const allValid = results.every(r => r.valid);
483
+ const message = `
484
+ ${allValid ? '✅' : '❌'} **Coherence Validation Results**
485
+
486
+ ${results.map(r => {
487
+ let output = r.valid ? '✅ Valid\n' : '❌ Invalid\n';
488
+ if (r.errors.length > 0) {
489
+ output += '\n**Errors:**\n' + r.errors.map(e => `- ${e}`).join('\n');
490
+ }
491
+ if (r.warnings.length > 0) {
492
+ output += '\n**Warnings:**\n' + r.warnings.map(w => `- ${w}`).join('\n');
493
+ }
494
+ if (r.hints.length > 0) {
495
+ output += '\n**Hints:**\n' + r.hints.map(h => `- ${h}`).join('\n');
496
+ }
497
+ return output;
498
+ }).join('\n\n')}
499
+ `;
500
+ return {
501
+ success: allValid,
502
+ result: results,
503
+ message
504
+ };
505
+ }
506
+ catch (error) {
507
+ return this.error(`Validation failed: ${error.message}`);
508
+ }
509
+ }
510
+ /**
511
+ * Convert modern JS to ES5
512
+ */
513
+ async convertToES5(args) {
514
+ let code = args.inline_code;
515
+ if (args.file_path && fs.existsSync(args.file_path)) {
516
+ code = fs.readFileSync(args.file_path, 'utf8');
517
+ }
518
+ if (!code) {
519
+ return this.error('No code provided to convert');
520
+ }
521
+ // Basic conversions (in production, use a proper transpiler)
522
+ let es5Code = code
523
+ // const/let → var
524
+ .replace(/\b(const|let)\s+/g, 'var ')
525
+ // Arrow functions
526
+ .replace(/(\w+)\s*=>\s*{/g, 'function($1) {')
527
+ .replace(/(\([^)]*\))\s*=>\s*{/g, 'function$1 {')
528
+ .replace(/(\w+)\s*=>\s*/g, 'function($1) { return ')
529
+ // Template literals (basic)
530
+ .replace(/`([^`]*)\$\{([^}]*)\}([^`]*)`/g, "'$1' + $2 + '$3'")
531
+ .replace(/`([^`]*)`/g, "'$1'")
532
+ // For...of → for loop
533
+ .replace(/for\s*\(\s*(?:const|let|var)\s+(\w+)\s+of\s+(\w+)\s*\)/g, 'for (var _i = 0; _i < $2.length; _i++) { var $1 = $2[_i];');
534
+ const message = `
535
+ ✅ **Code converted to ES5**
536
+
537
+ ⚠️ **Review the conversion carefully!**
538
+ This is a basic conversion. Complex features may need manual adjustment:
539
+ - Classes → function constructors
540
+ - async/await → callbacks
541
+ - Destructuring → individual assignments
542
+ - Spread operator → manual copying
543
+
544
+ **Common issues to check:**
545
+ - Arrow function this binding
546
+ - Default parameters
547
+ - Object method shorthand
548
+ `;
549
+ return {
550
+ success: true,
551
+ result: { es5Code },
552
+ message
553
+ };
554
+ }
555
+ /**
556
+ * Search in widgets (like Claude Code search)
557
+ */
558
+ async searchInWidgets(args) {
559
+ const { search_term, field = 'all', regex = false } = args;
560
+ // This would search in ServiceNow
561
+ // Similar to Claude Code's search but for ServiceNow widgets
562
+ return {
563
+ success: true,
564
+ result: {},
565
+ message: `Search results for "${search_term}" in widgets`
566
+ };
567
+ }
568
+ }
569
+ exports.ServiceNowLocalDevelopmentMCP = ServiceNowLocalDevelopmentMCP;
570
+ //# sourceMappingURL=servicenow-local-development-mcp.js.map