snow-flow 3.5.4 → 3.5.5

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.
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  /**
2
3
  * ServiceNow Local Development MCP Server
3
4
  *
@@ -7,42 +8,5 @@
7
8
  *
8
9
  * THIS IS THE KEY TO POWERFUL SERVICENOW DEVELOPMENT!
9
10
  */
10
- import { BaseMCPServer } from './base-mcp-server';
11
- export declare class ServiceNowLocalDevelopmentMCP extends BaseMCPServer {
12
- private syncManager;
13
- constructor();
14
- protected initializeTools(): Promise<void>;
15
- /**
16
- * DYNAMIC pull artifact to local files
17
- */
18
- private pullArtifact;
19
- /**
20
- * Push artifact changes back to ServiceNow
21
- */
22
- private pushArtifact;
23
- /**
24
- * Get sync status
25
- */
26
- private getSyncStatus;
27
- /**
28
- * Cleanup local files
29
- */
30
- private cleanup;
31
- /**
32
- * List supported artifact types
33
- */
34
- private listSupportedArtifacts;
35
- /**
36
- * Validate artifact coherence
37
- */
38
- private validateCoherence;
39
- /**
40
- * Convert modern JS to ES5
41
- */
42
- private convertToES5;
43
- /**
44
- * Search in widgets (like Claude Code search)
45
- */
46
- private searchInWidgets;
47
- }
11
+ export {};
48
12
  //# sourceMappingURL=servicenow-local-development-mcp.d.ts.map
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  /**
3
4
  * ServiceNow Local Development MCP Server
@@ -8,563 +9,425 @@
8
9
  *
9
10
  * THIS IS THE KEY TO POWERFUL SERVICENOW DEVELOPMENT!
10
11
  */
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
12
  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 {
13
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
14
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
15
+ const enhanced_base_mcp_server_js_1 = require("./shared/enhanced-base-mcp-server.js");
16
+ const artifact_local_sync_js_1 = require("../utils/artifact-local-sync.js");
17
+ const artifact_registry_js_1 = require("../utils/artifact-sync/artifact-registry.js");
18
+ class ServiceNowLocalDevelopmentMCP extends enhanced_base_mcp_server_js_1.EnhancedBaseMCPServer {
51
19
  constructor() {
52
20
  super('servicenow-local-development', '1.0.0');
53
- this.syncManager = new artifact_local_sync_1.ArtifactLocalSync(this.serviceNowClient);
21
+ // Initialize after client is available
22
+ this.setupSyncManager();
23
+ this.setupHandlers();
24
+ }
25
+ setupSyncManager() {
26
+ // Initialize sync manager with the client from enhanced base server
27
+ this.syncManager = new artifact_local_sync_js_1.ArtifactLocalSync(this.client);
28
+ this.logger.info('šŸ”§ Local sync manager initialized');
54
29
  }
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)()
30
+ setupHandlers() {
31
+ this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
32
+ tools: [
33
+ {
34
+ name: 'snow_pull_artifact',
35
+ description: `Pull ANY ServiceNow artifact to local files for editing with Claude Code's native tools. Automatically detects the artifact type and creates appropriate files based on the artifact registry. Supports: ${(0, artifact_registry_js_1.getSupportedTables)().map(t => (0, artifact_registry_js_1.getTableDisplayName)(t)).join(', ')}`,
36
+ inputSchema: {
37
+ type: 'object',
38
+ properties: {
39
+ sys_id: {
40
+ type: 'string',
41
+ description: 'Artifact sys_id to pull'
42
+ },
43
+ table: {
44
+ type: 'string',
45
+ description: 'Optional: Specify table name if known for faster processing',
46
+ enum: (0, artifact_registry_js_1.getSupportedTables)()
47
+ }
48
+ },
49
+ required: ['sys_id']
73
50
  }
74
51
  },
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'
52
+ {
53
+ name: 'snow_push_artifact',
54
+ description: 'Push local artifact changes back to ServiceNow with validation and coherence checking',
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {
58
+ sys_id: {
59
+ type: 'string',
60
+ description: 'Artifact sys_id to push back'
61
+ },
62
+ force: {
63
+ type: 'boolean',
64
+ description: 'Force push despite validation warnings',
65
+ default: false
66
+ }
67
+ },
68
+ required: ['sys_id']
89
69
  }
90
70
  },
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'
71
+ {
72
+ name: 'snow_validate_artifact_coherence',
73
+ description: 'Validate coherence and relationships between artifact components (e.g., widget HTML-client-server relationships)',
74
+ inputSchema: {
75
+ type: 'object',
76
+ properties: {
77
+ sys_id: {
78
+ type: 'string',
79
+ description: 'Artifact sys_id to validate'
80
+ }
81
+ },
82
+ required: ['sys_id']
104
83
  }
105
84
  },
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'
85
+ {
86
+ name: 'snow_list_supported_artifacts',
87
+ description: 'List all supported artifact types for local synchronization',
88
+ inputSchema: {
89
+ type: 'object',
90
+ properties: {},
91
+ additionalProperties: false
119
92
  }
120
93
  },
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
94
+ {
95
+ name: 'snow_sync_status',
96
+ description: 'Check sync status of local artifacts',
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ sys_id: {
101
+ type: 'string',
102
+ description: 'Optional: Check specific artifact, or all if omitted'
103
+ }
104
+ }
142
105
  }
143
106
  },
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'
107
+ {
108
+ name: 'snow_sync_cleanup',
109
+ description: 'Clean up local artifact files after successful sync',
110
+ inputSchema: {
111
+ type: 'object',
112
+ properties: {
113
+ sys_id: {
114
+ type: 'string',
115
+ description: 'Artifact sys_id to clean up'
116
+ },
117
+ force: {
118
+ type: 'boolean',
119
+ description: 'Force cleanup even with unsaved changes',
120
+ default: false
121
+ }
122
+ },
123
+ required: ['sys_id']
158
124
  }
159
125
  },
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
126
+ {
127
+ name: 'snow_convert_to_es5',
128
+ description: 'Convert modern JavaScript code to ES5 for ServiceNow compatibility',
129
+ inputSchema: {
130
+ type: 'object',
131
+ properties: {
132
+ code: {
133
+ type: 'string',
134
+ description: 'JavaScript code to convert to ES5'
135
+ },
136
+ context: {
137
+ type: 'string',
138
+ description: 'Context: server_script, client_script, business_rule, etc.',
139
+ enum: ['server_script', 'client_script', 'business_rule', 'script_include', 'ui_script']
140
+ }
141
+ },
142
+ required: ['code']
193
143
  }
194
144
  },
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'
145
+ // Legacy compatibility tools
146
+ {
147
+ name: 'snow_pull_widget',
148
+ description: 'Pull a ServiceNow widget to local files (legacy - use snow_pull_artifact instead)',
149
+ inputSchema: {
150
+ type: 'object',
151
+ properties: {
152
+ sys_id: {
153
+ type: 'string',
154
+ description: 'Widget sys_id to pull'
155
+ }
156
+ },
157
+ required: ['sys_id']
218
158
  }
219
159
  },
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'
160
+ {
161
+ name: 'snow_push_widget',
162
+ description: 'Push widget changes back to ServiceNow (legacy - use snow_push_artifact instead)',
163
+ inputSchema: {
164
+ type: 'object',
165
+ properties: {
166
+ sys_id: {
167
+ type: 'string',
168
+ description: 'Widget sys_id to push'
169
+ }
170
+ },
171
+ required: ['sys_id']
237
172
  }
238
173
  }
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)
174
+ ]
175
+ }));
176
+ this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
177
+ const { name, arguments: args } = request.params;
178
+ try {
179
+ this.logger.info(`šŸ”§ Executing tool: ${name}`, args);
180
+ let result;
181
+ switch (name) {
182
+ case 'snow_pull_artifact':
183
+ result = await this.pullArtifact(args);
184
+ break;
185
+ case 'snow_push_artifact':
186
+ result = await this.pushArtifact(args);
187
+ break;
188
+ case 'snow_validate_artifact_coherence':
189
+ result = await this.validateArtifactCoherence(args);
190
+ break;
191
+ case 'snow_sync_status':
192
+ result = await this.getSyncStatus(args);
193
+ break;
194
+ case 'snow_list_supported_artifacts':
195
+ result = await this.listSupportedArtifacts(args);
196
+ break;
197
+ case 'snow_sync_cleanup':
198
+ result = await this.syncCleanup(args);
199
+ break;
200
+ case 'snow_convert_to_es5':
201
+ result = await this.convertToES5(args);
202
+ break;
203
+ // Legacy compatibility
204
+ case 'snow_pull_widget':
205
+ result = await this.pullWidget(args);
206
+ break;
207
+ case 'snow_push_widget':
208
+ result = await this.pushWidget(args);
209
+ break;
210
+ default:
211
+ throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
212
+ }
213
+ this.logger.info(`āœ… Tool ${name} completed successfully`);
214
+ return result;
215
+ }
216
+ catch (error) {
217
+ const errorMessage = error instanceof Error ? error.message : String(error);
218
+ this.logger.error(`āŒ Tool ${name} failed: ${errorMessage}`);
219
+ return {
220
+ content: [
221
+ {
222
+ type: 'text',
223
+ text: `Error executing ${name}: ${errorMessage}`
224
+ }
225
+ ]
226
+ };
227
+ }
267
228
  });
268
229
  }
269
- /**
270
- * DYNAMIC pull artifact to local files
271
- */
272
230
  async pullArtifact(args) {
231
+ const { sys_id, table } = args;
273
232
  try {
274
233
  let artifact;
275
- if (args.table) {
276
- // Table specified - direct pull
277
- artifact = await this.syncManager.pullArtifact(args.table, args.sys_id);
234
+ if (table) {
235
+ // Use specified table
236
+ artifact = await this.syncManager.pullArtifact(table, sys_id);
278
237
  }
279
238
  else {
280
239
  // Auto-detect table
281
- artifact = await this.syncManager.pullArtifactBySysId(args.sys_id);
240
+ artifact = await this.syncManager.pullArtifactBySysId(sys_id);
282
241
  }
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
242
  return {
316
- success: true,
317
- result: artifact,
318
- message
243
+ content: [
244
+ {
245
+ type: 'text',
246
+ text: `āœ… Successfully pulled ${artifact.type} to local files at: ${artifact.localPath}\n\nšŸ“ Files created:\n${artifact.files.map(f => ` - ${f.filename} (${f.type})`).join('\n')}\n\nšŸ’” You can now use Claude Code's native tools to edit these files!`
247
+ }
248
+ ]
319
249
  };
320
250
  }
321
251
  catch (error) {
322
- return this.error(`Failed to pull artifact: ${error.message}`);
252
+ const errorMessage = error instanceof Error ? error.message : String(error);
253
+ return {
254
+ content: [
255
+ {
256
+ type: 'text',
257
+ text: `āŒ Failed to pull artifact: ${errorMessage}`
258
+ }
259
+ ]
260
+ };
323
261
  }
324
262
  }
325
- /**
326
- * Push artifact changes back to ServiceNow
327
- */
328
263
  async pushArtifact(args) {
264
+ const { sys_id, force = false } = args;
329
265
  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
- }
266
+ const success = await this.syncManager.pushArtifact(sys_id);
267
+ return {
268
+ content: [
269
+ {
270
+ type: 'text',
271
+ text: success
272
+ ? `āœ… Successfully pushed changes back to ServiceNow!`
273
+ : `āŒ Failed to push changes. Check logs for details.`
274
+ }
275
+ ]
276
+ };
372
277
  }
373
278
  catch (error) {
374
- return this.error(`Failed to push artifact: ${error.message}`);
279
+ const errorMessage = error instanceof Error ? error.message : String(error);
280
+ return {
281
+ content: [
282
+ {
283
+ type: 'text',
284
+ text: `āŒ Failed to push artifact: ${errorMessage}`
285
+ }
286
+ ]
287
+ };
375
288
  }
376
289
  }
377
- /**
378
- * Get sync status
379
- */
380
290
  async getSyncStatus(args) {
381
- const artifacts = this.syncManager.listLocalArtifacts();
382
- if (args.sys_id) {
383
- const status = this.syncManager.getSyncStatus(args.sys_id);
291
+ const { sys_id } = args;
292
+ if (sys_id) {
293
+ const status = this.syncManager.getSyncStatus(sys_id);
384
294
  return {
385
- success: true,
386
- result: { status },
387
- message: `Sync status for ${args.sys_id}: ${status}`
295
+ content: [
296
+ {
297
+ type: 'text',
298
+ text: `Sync status for ${sys_id}: ${status}`
299
+ }
300
+ ]
388
301
  };
389
302
  }
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);
303
+ else {
304
+ const artifacts = this.syncManager.listLocalArtifacts();
305
+ const statusText = artifacts.length > 0
306
+ ? artifacts.map(a => `${a.name} (${a.sys_id}): ${a.syncStatus}`).join('\n')
307
+ : 'No local artifacts found';
419
308
  return {
420
- success: true,
421
- result: { cleaned: true },
422
- message: `āœ… Local files cleaned up successfully`
309
+ content: [
310
+ {
311
+ type: 'text',
312
+ text: `Local artifacts status:\n${statusText}`
313
+ }
314
+ ]
423
315
  };
424
316
  }
425
- catch (error) {
426
- return this.error(`Cleanup failed: ${error.message}`);
427
- }
428
317
  }
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];
318
+ async listSupportedArtifacts(args) {
319
+ const supportedTypes = (0, artifact_registry_js_1.getSupportedTables)().map(table => {
320
+ const config = artifact_registry_js_1.ARTIFACT_REGISTRY[table];
436
321
  return {
437
322
  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)
323
+ displayName: config?.displayName || table,
324
+ folderName: config?.folderName || table,
325
+ fields: config?.fieldMappings.length || 0,
326
+ hasCoherence: (config?.coherenceRules?.length || 0) > 0,
327
+ requiresES5: config?.fieldMappings.some(fm => fm.validateES5) || false
443
328
  };
444
329
  });
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
330
  return {
464
- success: true,
465
- result: details,
466
- message
331
+ content: [
332
+ {
333
+ type: 'text',
334
+ text: `Supported ServiceNow artifact types for local sync:\n\n${supportedTypes.map(t => `šŸ“¦ ${t.displayName} (${t.table})\n └── ${t.fields} fields, ES5: ${t.requiresES5 ? 'āœ…' : 'āŒ'}, Coherence: ${t.hasCoherence ? 'āœ…' : 'āŒ'}`).join('\n\n')}\n\nTotal: ${supportedTypes.length} artifact types supported`
335
+ }
336
+ ]
467
337
  };
468
338
  }
469
- /**
470
- * Validate artifact coherence
471
- */
472
- async validateCoherence(args) {
339
+ async validateArtifactCoherence(args) {
340
+ const { sys_id } = args;
473
341
  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
- `;
342
+ const results = await this.syncManager.validateArtifactCoherence(sys_id);
343
+ const hasErrors = results.some(r => !r.valid);
500
344
  return {
501
- success: allValid,
502
- result: results,
503
- message
345
+ content: [
346
+ {
347
+ type: 'text',
348
+ text: hasErrors
349
+ ? `āš ļø Coherence validation found issues:\n${results.filter(r => !r.valid).map(r => r.errors.join(', ')).join('\n')}`
350
+ : `āœ… Artifact coherence validation passed!`
351
+ }
352
+ ]
504
353
  };
505
354
  }
506
355
  catch (error) {
507
- return this.error(`Validation failed: ${error.message}`);
356
+ const errorMessage = error instanceof Error ? error.message : String(error);
357
+ return {
358
+ content: [
359
+ {
360
+ type: 'text',
361
+ text: `āŒ Failed to validate coherence: ${errorMessage}`
362
+ }
363
+ ]
364
+ };
508
365
  }
509
366
  }
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');
367
+ async syncCleanup(args) {
368
+ const { sys_id, force = false } = args;
369
+ try {
370
+ await this.syncManager.cleanup(sys_id, force);
371
+ return {
372
+ content: [
373
+ {
374
+ type: 'text',
375
+ text: `āœ… Successfully cleaned up local files for ${sys_id}`
376
+ }
377
+ ]
378
+ };
517
379
  }
518
- if (!code) {
519
- return this.error('No code provided to convert');
380
+ catch (error) {
381
+ const errorMessage = error instanceof Error ? error.message : String(error);
382
+ return {
383
+ content: [
384
+ {
385
+ type: 'text',
386
+ text: `āŒ Failed to cleanup: ${errorMessage}`
387
+ }
388
+ ]
389
+ };
520
390
  }
521
- // Basic conversions (in production, use a proper transpiler)
391
+ }
392
+ async convertToES5(args) {
393
+ const { code, context = 'server_script' } = args;
394
+ // Basic ES5 conversion - in a real implementation this would be more sophisticated
522
395
  let es5Code = code
523
- // const/let → var
524
- .replace(/\b(const|let)\s+/g, 'var ')
525
- // Arrow functions
396
+ .replace(/\bconst\s+/g, 'var ')
397
+ .replace(/\blet\s+/g, 'var ')
526
398
  .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
- `;
399
+ .replace(/(\w+)\s*=>\s*([^{])/g, 'function($1) { return $2; }')
400
+ .replace(/`([^`]*)`/g, (match, content) => {
401
+ return '"' + content.replace(/\$\{([^}]+)\}/g, '" + $1 + "') + '"';
402
+ });
549
403
  return {
550
- success: true,
551
- result: { es5Code },
552
- message
404
+ content: [
405
+ {
406
+ type: 'text',
407
+ text: `āœ… Converted to ES5 (basic conversion):\n\n\`\`\`javascript\n${es5Code}\n\`\`\`\n\nāš ļø Note: This is a basic conversion. Please review and test the code.`
408
+ }
409
+ ]
553
410
  };
554
411
  }
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
- };
412
+ // Legacy compatibility methods
413
+ async pullWidget(args) {
414
+ return this.pullArtifact({ ...args, table: 'sp_widget' });
415
+ }
416
+ async pushWidget(args) {
417
+ return this.pushArtifact(args);
567
418
  }
568
419
  }
569
- exports.ServiceNowLocalDevelopmentMCP = ServiceNowLocalDevelopmentMCP;
420
+ // Start the server
421
+ async function main() {
422
+ const server = new ServiceNowLocalDevelopmentMCP();
423
+ const transport = new stdio_js_1.StdioServerTransport();
424
+ await server.server.connect(transport);
425
+ console.error('šŸš€ ServiceNow Local Development MCP Server started');
426
+ }
427
+ if (require.main === module) {
428
+ main().catch((error) => {
429
+ console.error('āŒ Server failed to start:', error);
430
+ process.exit(1);
431
+ });
432
+ }
570
433
  //# sourceMappingURL=servicenow-local-development-mcp.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.5.4",
3
+ "version": "3.5.5",
4
4
  "description": "ServiceNow development framework with MCP server integration. Executes background scripts using ES5 JavaScript only (ServiceNow Rhino engine requirement). Provides 18 MCP servers including local development sync for editing ServiceNow artifacts with Claude Code native tools, widget deployment with coherence validation, table operations, script execution, machine learning, advanced features, and comprehensive platform management.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",