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.
- package/README.md +11 -9
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -2
- package/dist/mcp/enhancements/smart-query-enhancement.d.ts +49 -0
- package/dist/mcp/enhancements/smart-query-enhancement.js +233 -0
- package/dist/mcp/servicenow-local-development-mcp.d.ts +48 -0
- package/dist/mcp/servicenow-local-development-mcp.js +570 -0
- package/dist/queen/queen-knowledge-base.d.ts +151 -0
- package/dist/queen/queen-knowledge-base.js +283 -0
- package/dist/queen/servicenow-queen.d.ts +2 -0
- package/dist/queen/servicenow-queen.js +91 -0
- package/dist/utils/artifact-local-sync.d.ts +115 -0
- package/dist/utils/artifact-local-sync.js +705 -0
- package/dist/utils/artifact-sync/artifact-registry.d.ts +66 -0
- package/dist/utils/artifact-sync/artifact-registry.js +450 -0
- package/dist/utils/artifact-sync/index.d.ts +33 -0
- package/dist/utils/artifact-sync/index.js +52 -0
- package/dist/utils/mcp-tool-registry.js +109 -0
- package/dist/utils/smart-field-fetcher.d.ts +68 -0
- package/dist/utils/smart-field-fetcher.js +395 -0
- package/package.json +2 -2
- package/website/.dockerignore +64 -0
- package/website/Dockerfile +36 -0
- package/website/README.md +40 -1
- package/website/cloudbuild.yaml +69 -0
- package/website/css/style.css +119 -1
- package/website/index.html +385 -39
- package/website/js/main.js +26 -1
- package/website/nginx.conf +116 -0
- package/website/service.yaml +61 -0
|
@@ -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
|