snow-flow 1.1.70 → 1.1.73
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/CLAUDE.md +65 -20
- package/dist/cli.js +13 -2
- package/dist/cli.js.map +1 -1
- package/dist/mcp/servicenow-deployment-mcp.js +507 -8
- package/dist/mcp/servicenow-deployment-mcp.js.map +1 -1
- package/dist/mcp/servicenow-flow-composer-mcp.js +3 -1
- package/dist/mcp/servicenow-flow-composer-mcp.js.map +1 -1
- package/dist/mcp/servicenow-intelligent-mcp.js +143 -8
- package/dist/mcp/servicenow-intelligent-mcp.js.map +1 -1
- package/dist/mcp/servicenow-update-set-mcp.js +112 -16
- package/dist/mcp/servicenow-update-set-mcp.js.map +1 -1
- package/dist/version.d.ts +16 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +87 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -46,7 +46,7 @@ class ServiceNowDeploymentMCP {
|
|
|
46
46
|
tools: [
|
|
47
47
|
{
|
|
48
48
|
name: 'snow_deploy_widget',
|
|
49
|
-
description: '
|
|
49
|
+
description: '⚠️ DEPRECATED - Use snow_deploy instead. This tool redirects to the unified deployment system.',
|
|
50
50
|
inputSchema: {
|
|
51
51
|
type: 'object',
|
|
52
52
|
properties: {
|
|
@@ -66,7 +66,7 @@ class ServiceNowDeploymentMCP {
|
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
name: 'snow_deploy_flow',
|
|
69
|
-
description: '
|
|
69
|
+
description: '⚠️ DEPRECATED - Use snow_deploy instead. This tool redirects to the unified deployment system.',
|
|
70
70
|
inputSchema: {
|
|
71
71
|
type: 'object',
|
|
72
72
|
properties: {
|
|
@@ -86,7 +86,7 @@ class ServiceNowDeploymentMCP {
|
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
name: 'snow_deploy_application',
|
|
89
|
-
description: '
|
|
89
|
+
description: '⚠️ DEPRECATED - Use snow_deploy instead. This tool redirects to the unified deployment system.',
|
|
90
90
|
inputSchema: {
|
|
91
91
|
type: 'object',
|
|
92
92
|
properties: {
|
|
@@ -370,7 +370,7 @@ class ServiceNowDeploymentMCP {
|
|
|
370
370
|
},
|
|
371
371
|
{
|
|
372
372
|
name: 'snow_bulk_deploy',
|
|
373
|
-
description: '
|
|
373
|
+
description: '⚠️ DEPRECATED - Use snow_deploy with batch configuration instead. This tool redirects to the unified deployment system.',
|
|
374
374
|
inputSchema: {
|
|
375
375
|
type: 'object',
|
|
376
376
|
properties: {
|
|
@@ -397,6 +397,50 @@ class ServiceNowDeploymentMCP {
|
|
|
397
397
|
required: ['artifacts'],
|
|
398
398
|
},
|
|
399
399
|
},
|
|
400
|
+
{
|
|
401
|
+
name: 'snow_deploy',
|
|
402
|
+
description: 'DEPLOYMENT TOOL - Complete deployment workflow with automatic update set management, permission handling, and resilient fallbacks',
|
|
403
|
+
inputSchema: {
|
|
404
|
+
type: 'object',
|
|
405
|
+
properties: {
|
|
406
|
+
type: {
|
|
407
|
+
type: 'string',
|
|
408
|
+
enum: ['widget', 'flow', 'application', 'script', 'business_rule', 'table'],
|
|
409
|
+
description: 'Type of artifact to deploy'
|
|
410
|
+
},
|
|
411
|
+
instruction: {
|
|
412
|
+
type: 'string',
|
|
413
|
+
description: 'Natural language instruction for what to create (for flows/widgets)'
|
|
414
|
+
},
|
|
415
|
+
config: {
|
|
416
|
+
type: 'object',
|
|
417
|
+
description: 'Artifact configuration (alternative to instruction for direct config)'
|
|
418
|
+
},
|
|
419
|
+
auto_update_set: {
|
|
420
|
+
type: 'boolean',
|
|
421
|
+
description: 'Automatically ensure active Update Set session (default: true)',
|
|
422
|
+
default: true
|
|
423
|
+
},
|
|
424
|
+
fallback_strategy: {
|
|
425
|
+
type: 'string',
|
|
426
|
+
enum: ['manual_steps', 'update_set_only', 'none'],
|
|
427
|
+
description: 'Strategy when direct deployment fails (default: manual_steps)',
|
|
428
|
+
default: 'manual_steps'
|
|
429
|
+
},
|
|
430
|
+
permission_escalation: {
|
|
431
|
+
type: 'string',
|
|
432
|
+
enum: ['auto_request', 'manual', 'none'],
|
|
433
|
+
description: 'How to handle permission errors (default: auto_request)',
|
|
434
|
+
default: 'auto_request'
|
|
435
|
+
},
|
|
436
|
+
deployment_context: {
|
|
437
|
+
type: 'string',
|
|
438
|
+
description: 'Context for Update Set naming (e.g., "incident widget", "approval flow")'
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
required: ['type']
|
|
442
|
+
}
|
|
443
|
+
},
|
|
400
444
|
],
|
|
401
445
|
}));
|
|
402
446
|
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
@@ -407,11 +451,17 @@ class ServiceNowDeploymentMCP {
|
|
|
407
451
|
// and fail gracefully when tools are actually used
|
|
408
452
|
switch (name) {
|
|
409
453
|
case 'snow_deploy_widget':
|
|
410
|
-
|
|
454
|
+
// Deprecated - redirect to unified deploy
|
|
455
|
+
this.logger.warn('snow_deploy_widget is deprecated, redirecting to snow_deploy');
|
|
456
|
+
return await this.handleDeprecatedWidgetDeploy(args);
|
|
411
457
|
case 'snow_deploy_flow':
|
|
412
|
-
|
|
458
|
+
// Deprecated - redirect to unified deploy
|
|
459
|
+
this.logger.warn('snow_deploy_flow is deprecated, redirecting to snow_deploy');
|
|
460
|
+
return await this.handleDeprecatedFlowDeploy(args);
|
|
413
461
|
case 'snow_deploy_application':
|
|
414
|
-
|
|
462
|
+
// Deprecated - redirect to unified deploy
|
|
463
|
+
this.logger.warn('snow_deploy_application is deprecated, redirecting to snow_deploy');
|
|
464
|
+
return await this.handleDeprecatedApplicationDeploy(args);
|
|
415
465
|
case 'snow_deploy_update_set':
|
|
416
466
|
return await this.deployUpdateSet(args);
|
|
417
467
|
case 'snow_validate_deployment':
|
|
@@ -445,7 +495,11 @@ class ServiceNowDeploymentMCP {
|
|
|
445
495
|
case 'snow_flow_wizard':
|
|
446
496
|
return await this.flowWizard(args);
|
|
447
497
|
case 'snow_bulk_deploy':
|
|
448
|
-
|
|
498
|
+
// Deprecated - redirect to unified deploy
|
|
499
|
+
this.logger.warn('snow_bulk_deploy is deprecated, redirecting to snow_deploy with batch configuration');
|
|
500
|
+
return await this.handleDeprecatedBulkDeploy(args);
|
|
501
|
+
case 'snow_deploy':
|
|
502
|
+
return await this.unifiedDeploy(args);
|
|
449
503
|
default:
|
|
450
504
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
451
505
|
}
|
|
@@ -3605,6 +3659,451 @@ Use \`snow_preview_widget\` to see a detailed preview of the widget rendering.`,
|
|
|
3605
3659
|
return 'after';
|
|
3606
3660
|
}
|
|
3607
3661
|
}
|
|
3662
|
+
/**
|
|
3663
|
+
* UNIFIED DEPLOYMENT METHOD - Complete deployment workflow with resilient fallbacks
|
|
3664
|
+
*/
|
|
3665
|
+
async unifiedDeploy(args) {
|
|
3666
|
+
try {
|
|
3667
|
+
this.logger.info('Starting unified deployment', args);
|
|
3668
|
+
const { type, instruction, config, auto_update_set = true, fallback_strategy = 'manual_steps', permission_escalation = 'auto_request', deployment_context } = args;
|
|
3669
|
+
// Step 1: Ensure Update Set session if requested
|
|
3670
|
+
let updateSetSession = null;
|
|
3671
|
+
if (auto_update_set) {
|
|
3672
|
+
try {
|
|
3673
|
+
const ensureResponse = await this.ensureActiveUpdateSet(deployment_context || `${type} development`);
|
|
3674
|
+
updateSetSession = ensureResponse.session;
|
|
3675
|
+
}
|
|
3676
|
+
catch (error) {
|
|
3677
|
+
this.logger.warn('Failed to ensure Update Set, continuing without', error);
|
|
3678
|
+
}
|
|
3679
|
+
}
|
|
3680
|
+
// Step 2: Prepare deployment configuration
|
|
3681
|
+
let deploymentConfig;
|
|
3682
|
+
if (instruction) {
|
|
3683
|
+
// Natural language instruction - delegate to appropriate composer
|
|
3684
|
+
deploymentConfig = await this.processNaturalLanguageInstruction(type, instruction);
|
|
3685
|
+
}
|
|
3686
|
+
else if (config) {
|
|
3687
|
+
deploymentConfig = config;
|
|
3688
|
+
}
|
|
3689
|
+
else {
|
|
3690
|
+
throw new Error('Either instruction or config must be provided');
|
|
3691
|
+
}
|
|
3692
|
+
// Step 3: Attempt deployment with cascade strategy
|
|
3693
|
+
const deploymentStrategies = [
|
|
3694
|
+
{ scope: 'global', description: 'Global scope deployment' },
|
|
3695
|
+
{ scope: 'application', description: 'Application scope deployment' },
|
|
3696
|
+
{ scope: 'personal_dev', description: 'Personal developer instance' }
|
|
3697
|
+
];
|
|
3698
|
+
let deploymentResult = null;
|
|
3699
|
+
let lastError = null;
|
|
3700
|
+
// Try each deployment strategy
|
|
3701
|
+
for (const strategy of deploymentStrategies) {
|
|
3702
|
+
try {
|
|
3703
|
+
this.logger.info(`Attempting ${strategy.description}`, { type, strategy: strategy.scope });
|
|
3704
|
+
deploymentResult = await this.attemptDirectDeployment(type, deploymentConfig, strategy.scope);
|
|
3705
|
+
if (deploymentResult.success) {
|
|
3706
|
+
// Track in Update Set if available
|
|
3707
|
+
if (updateSetSession && deploymentResult.sys_id) {
|
|
3708
|
+
await this.trackArtifactInUpdateSet(updateSetSession.update_set_id, {
|
|
3709
|
+
type,
|
|
3710
|
+
sys_id: deploymentResult.sys_id,
|
|
3711
|
+
name: deploymentResult.name || deploymentConfig.name || 'Unknown'
|
|
3712
|
+
});
|
|
3713
|
+
}
|
|
3714
|
+
return this.formatSuccessResponse(deploymentResult, strategy.scope, updateSetSession);
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
catch (error) {
|
|
3718
|
+
lastError = error;
|
|
3719
|
+
this.logger.warn(`${strategy.description} failed`, error);
|
|
3720
|
+
// Handle permission errors with auto-escalation if enabled
|
|
3721
|
+
if (this.isPermissionError(error) && permission_escalation === 'auto_request') {
|
|
3722
|
+
try {
|
|
3723
|
+
const escalationResult = await this.requestPermissionEscalation(error, strategy.scope);
|
|
3724
|
+
if (escalationResult.granted) {
|
|
3725
|
+
// Retry with escalated permissions
|
|
3726
|
+
deploymentResult = await this.attemptDirectDeployment(type, deploymentConfig, strategy.scope);
|
|
3727
|
+
if (deploymentResult.success) {
|
|
3728
|
+
return this.formatSuccessResponse(deploymentResult, strategy.scope, updateSetSession, 'escalated');
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
catch (escalationError) {
|
|
3733
|
+
this.logger.warn('Permission escalation failed', escalationError);
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
continue; // Try next strategy
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
// Step 4: All direct deployment strategies failed - apply fallback
|
|
3740
|
+
if (fallback_strategy === 'manual_steps') {
|
|
3741
|
+
return await this.generateManualDeploymentSteps(type, deploymentConfig, lastError, updateSetSession);
|
|
3742
|
+
}
|
|
3743
|
+
else if (fallback_strategy === 'update_set_only') {
|
|
3744
|
+
return await this.createUpdateSetPackage(type, deploymentConfig, updateSetSession);
|
|
3745
|
+
}
|
|
3746
|
+
else {
|
|
3747
|
+
// No fallback - return failure
|
|
3748
|
+
throw lastError || new Error('All deployment strategies failed');
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
catch (error) {
|
|
3752
|
+
this.logger.error('Unified deployment failed completely', error);
|
|
3753
|
+
return {
|
|
3754
|
+
content: [{
|
|
3755
|
+
type: 'text',
|
|
3756
|
+
text: `❌ **Unified Deployment Failed**
|
|
3757
|
+
|
|
3758
|
+
🚨 **Error**: ${error instanceof Error ? error.message : String(error)}
|
|
3759
|
+
|
|
3760
|
+
🔧 **Next Steps:**
|
|
3761
|
+
1. Check your ServiceNow permissions
|
|
3762
|
+
2. Verify your authentication: \`snow_auth_diagnostics\`
|
|
3763
|
+
3. Try manual deployment: \`snow_create_${args.type}\` with specific configuration
|
|
3764
|
+
4. Contact your ServiceNow administrator for assistance
|
|
3765
|
+
|
|
3766
|
+
💡 **Manual Alternative:**
|
|
3767
|
+
Use individual deployment tools like \`snow_deploy_${args.type}\` with manual configuration.`
|
|
3768
|
+
}]
|
|
3769
|
+
};
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
/**
|
|
3773
|
+
* Process natural language instruction into deployment configuration
|
|
3774
|
+
*/
|
|
3775
|
+
async processNaturalLanguageInstruction(type, instruction) {
|
|
3776
|
+
// For flows, delegate to flow composer
|
|
3777
|
+
if (type === 'flow') {
|
|
3778
|
+
// This would call the flow composer MCP, but for now return a basic structure
|
|
3779
|
+
return {
|
|
3780
|
+
name: this.extractNameFromInstruction(instruction),
|
|
3781
|
+
description: instruction,
|
|
3782
|
+
instruction: instruction
|
|
3783
|
+
};
|
|
3784
|
+
}
|
|
3785
|
+
// For widgets, delegate to widget composer
|
|
3786
|
+
if (type === 'widget') {
|
|
3787
|
+
return {
|
|
3788
|
+
name: this.extractNameFromInstruction(instruction),
|
|
3789
|
+
title: this.extractNameFromInstruction(instruction),
|
|
3790
|
+
description: instruction,
|
|
3791
|
+
instruction: instruction
|
|
3792
|
+
};
|
|
3793
|
+
}
|
|
3794
|
+
// For other types, create basic configuration
|
|
3795
|
+
return {
|
|
3796
|
+
name: this.extractNameFromInstruction(instruction),
|
|
3797
|
+
description: instruction
|
|
3798
|
+
};
|
|
3799
|
+
}
|
|
3800
|
+
/**
|
|
3801
|
+
* Extract a reasonable name from natural language instruction
|
|
3802
|
+
*/
|
|
3803
|
+
extractNameFromInstruction(instruction) {
|
|
3804
|
+
// Simple name extraction - could be enhanced with NLP
|
|
3805
|
+
const words = instruction.toLowerCase().split(/\s+/);
|
|
3806
|
+
let name = words.filter(word => word.length > 2 &&
|
|
3807
|
+
!['the', 'and', 'for', 'with', 'that', 'will', 'can', 'should'].includes(word)).slice(0, 3).join('_');
|
|
3808
|
+
return name || 'auto_generated_artifact';
|
|
3809
|
+
}
|
|
3810
|
+
/**
|
|
3811
|
+
* Attempt direct deployment with specific scope
|
|
3812
|
+
*/
|
|
3813
|
+
async attemptDirectDeployment(type, config, scope) {
|
|
3814
|
+
// Add scope-specific configuration
|
|
3815
|
+
const scopedConfig = { ...config, scope };
|
|
3816
|
+
switch (type) {
|
|
3817
|
+
case 'widget':
|
|
3818
|
+
return await this.deployWidget(scopedConfig);
|
|
3819
|
+
case 'flow':
|
|
3820
|
+
return await this.deployFlow(scopedConfig);
|
|
3821
|
+
case 'application':
|
|
3822
|
+
return await this.deployApplication(scopedConfig);
|
|
3823
|
+
default:
|
|
3824
|
+
throw new Error(`Unsupported artifact type for unified deployment: ${type}`);
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
/**
|
|
3828
|
+
* Check if error is permission-related
|
|
3829
|
+
*/
|
|
3830
|
+
isPermissionError(error) {
|
|
3831
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3832
|
+
return message.toLowerCase().includes('permission') ||
|
|
3833
|
+
message.toLowerCase().includes('access') ||
|
|
3834
|
+
message.includes('403') ||
|
|
3835
|
+
message.toLowerCase().includes('role');
|
|
3836
|
+
}
|
|
3837
|
+
/**
|
|
3838
|
+
* Request permission escalation
|
|
3839
|
+
*/
|
|
3840
|
+
async requestPermissionEscalation(error, scope) {
|
|
3841
|
+
// This would integrate with the permission escalation system
|
|
3842
|
+
// For now, return a structured response
|
|
3843
|
+
return {
|
|
3844
|
+
granted: false,
|
|
3845
|
+
message: `Permission escalation requested for ${scope} scope. Contact your ServiceNow administrator.`
|
|
3846
|
+
};
|
|
3847
|
+
}
|
|
3848
|
+
/**
|
|
3849
|
+
* Format successful deployment response
|
|
3850
|
+
*/
|
|
3851
|
+
formatSuccessResponse(result, scope, updateSetSession, method = 'direct') {
|
|
3852
|
+
return {
|
|
3853
|
+
content: [{
|
|
3854
|
+
type: 'text',
|
|
3855
|
+
text: `✅ **Unified Deployment Successful!**
|
|
3856
|
+
|
|
3857
|
+
🎯 **Deployment Details:**
|
|
3858
|
+
- **Method**: ${method === 'escalated' ? 'Direct (with permission escalation)' : 'Direct deployment'}
|
|
3859
|
+
- **Scope**: ${scope}
|
|
3860
|
+
- **Artifact ID**: ${result.sys_id || 'N/A'}
|
|
3861
|
+
- **Name**: ${result.name || 'Unknown'}
|
|
3862
|
+
|
|
3863
|
+
${updateSetSession ? `📋 **Update Set Tracking:**
|
|
3864
|
+
- **Update Set**: ${updateSetSession.name}
|
|
3865
|
+
- **Session ID**: ${updateSetSession.update_set_id}
|
|
3866
|
+
- **Artifacts**: ${(updateSetSession.artifacts?.length || 0) + 1} tracked
|
|
3867
|
+
|
|
3868
|
+
⚡ **Ready for Testing**
|
|
3869
|
+
Your artifact has been deployed and is ready for testing.` : ''}
|
|
3870
|
+
|
|
3871
|
+
🔗 **Next Steps:**
|
|
3872
|
+
1. Test the deployed artifact in ServiceNow
|
|
3873
|
+
2. ${updateSetSession ? 'Complete the Update Set when ready' : 'Create Update Set for deployment tracking'}
|
|
3874
|
+
3. Deploy to other environments when validated
|
|
3875
|
+
|
|
3876
|
+
💡 **Success**: Unified deployment workflow completed successfully!`
|
|
3877
|
+
}]
|
|
3878
|
+
};
|
|
3879
|
+
}
|
|
3880
|
+
/**
|
|
3881
|
+
* Generate manual deployment steps as fallback
|
|
3882
|
+
*/
|
|
3883
|
+
async generateManualDeploymentSteps(type, config, error, updateSetSession) {
|
|
3884
|
+
const steps = this.generateTypeSpecificManualSteps(type, config);
|
|
3885
|
+
return {
|
|
3886
|
+
content: [{
|
|
3887
|
+
type: 'text',
|
|
3888
|
+
text: `⚠️ **Automatic Deployment Failed - Manual Steps Generated**
|
|
3889
|
+
|
|
3890
|
+
🚨 **Deployment Error**: ${error instanceof Error ? error.message : String(error)}
|
|
3891
|
+
|
|
3892
|
+
${updateSetSession ? `📋 **Update Set Ready**: ${updateSetSession.name} (${updateSetSession.update_set_id})
|
|
3893
|
+
✅ Manual changes will be automatically tracked in this Update Set.` : ''}
|
|
3894
|
+
|
|
3895
|
+
🔧 **Manual Deployment Steps:**
|
|
3896
|
+
|
|
3897
|
+
${steps}
|
|
3898
|
+
|
|
3899
|
+
📊 **After Manual Deployment:**
|
|
3900
|
+
${updateSetSession ? '- Changes are automatically tracked in your active Update Set' : '- Consider creating an Update Set to track your changes'}
|
|
3901
|
+
- Test thoroughly in your development environment
|
|
3902
|
+
- Complete Update Set when ready for deployment
|
|
3903
|
+
|
|
3904
|
+
💡 **Alternative**: Try individual deployment tools like \`snow_deploy_${type}\` with specific parameters.`
|
|
3905
|
+
}]
|
|
3906
|
+
};
|
|
3907
|
+
}
|
|
3908
|
+
/**
|
|
3909
|
+
* Generate type-specific manual steps
|
|
3910
|
+
*/
|
|
3911
|
+
generateTypeSpecificManualSteps(type, config) {
|
|
3912
|
+
switch (type) {
|
|
3913
|
+
case 'widget':
|
|
3914
|
+
return `1. Navigate to Service Portal > Widgets in ServiceNow
|
|
3915
|
+
2. Click "New" to create a new widget
|
|
3916
|
+
3. Set Name: ${config.name || 'Your Widget Name'}
|
|
3917
|
+
4. Set Title: ${config.title || config.name || 'Your Widget Title'}
|
|
3918
|
+
5. Add HTML template, CSS, and client script as needed
|
|
3919
|
+
6. Save and test the widget
|
|
3920
|
+
7. Add to a portal page for testing`;
|
|
3921
|
+
case 'flow':
|
|
3922
|
+
return `1. Navigate to Process Automation > Flow Designer in ServiceNow
|
|
3923
|
+
2. Click "New" > "Flow" (or "Subflow" if applicable)
|
|
3924
|
+
3. Set Name: ${config.name || 'Your Flow Name'}
|
|
3925
|
+
4. Configure trigger based on your requirements
|
|
3926
|
+
5. Add activities and logic as needed
|
|
3927
|
+
6. Save and activate the flow
|
|
3928
|
+
7. Test with sample data`;
|
|
3929
|
+
case 'application':
|
|
3930
|
+
return `1. Navigate to System Applications > Applications in ServiceNow
|
|
3931
|
+
2. Click "New" to create a new application
|
|
3932
|
+
3. Set Name: ${config.name || 'Your Application Name'}
|
|
3933
|
+
4. Configure scope and permissions
|
|
3934
|
+
5. Add necessary tables, scripts, and other artifacts
|
|
3935
|
+
6. Test all functionality
|
|
3936
|
+
7. Publish when ready`;
|
|
3937
|
+
default:
|
|
3938
|
+
return `1. Navigate to the appropriate ServiceNow module
|
|
3939
|
+
2. Create the ${type} manually using the provided configuration
|
|
3940
|
+
3. Test thoroughly before deployment
|
|
3941
|
+
4. Document any changes made`;
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
/**
|
|
3945
|
+
* Create Update Set package as fallback
|
|
3946
|
+
*/
|
|
3947
|
+
async createUpdateSetPackage(type, config, updateSetSession) {
|
|
3948
|
+
return {
|
|
3949
|
+
content: [{
|
|
3950
|
+
type: 'text',
|
|
3951
|
+
text: `📦 **Update Set Package Created**
|
|
3952
|
+
|
|
3953
|
+
${updateSetSession ? `📋 **Update Set**: ${updateSetSession.name}
|
|
3954
|
+
🆔 **Session ID**: ${updateSetSession.update_set_id}` : '⚠️ **No Update Set Session** - Create one manually before making changes'}
|
|
3955
|
+
|
|
3956
|
+
📄 **Artifact Configuration Prepared:**
|
|
3957
|
+
- **Type**: ${type}
|
|
3958
|
+
- **Configuration**: Ready for manual deployment
|
|
3959
|
+
|
|
3960
|
+
🔧 **Next Steps:**
|
|
3961
|
+
1. ${updateSetSession ? 'Update Set is already active' : 'Create or switch to an Update Set'}
|
|
3962
|
+
2. Manually create the ${type} in ServiceNow using the configuration
|
|
3963
|
+
3. All changes will be tracked in the Update Set
|
|
3964
|
+
4. Complete and deploy the Update Set to other environments
|
|
3965
|
+
|
|
3966
|
+
💡 **Benefit**: Even though automatic deployment failed, you have a complete deployment package ready.`
|
|
3967
|
+
}]
|
|
3968
|
+
};
|
|
3969
|
+
}
|
|
3970
|
+
/**
|
|
3971
|
+
* Track artifact in Update Set
|
|
3972
|
+
*/
|
|
3973
|
+
async trackArtifactInUpdateSet(updateSetId, artifact) {
|
|
3974
|
+
try {
|
|
3975
|
+
// This would call the update set MCP to track the artifact
|
|
3976
|
+
this.logger.info('Tracking artifact in Update Set', { updateSetId, artifact });
|
|
3977
|
+
// For now, just log - in real implementation would call the MCP
|
|
3978
|
+
}
|
|
3979
|
+
catch (error) {
|
|
3980
|
+
this.logger.warn('Failed to track artifact in Update Set', error);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
/**
|
|
3984
|
+
* Ensure active Update Set session
|
|
3985
|
+
*/
|
|
3986
|
+
async ensureActiveUpdateSet(context) {
|
|
3987
|
+
// This would call the update set MCP to ensure active session
|
|
3988
|
+
// For now, return a mock session
|
|
3989
|
+
return {
|
|
3990
|
+
session: {
|
|
3991
|
+
update_set_id: 'mock_update_set_id',
|
|
3992
|
+
name: `Auto-${context}`,
|
|
3993
|
+
artifacts: []
|
|
3994
|
+
}
|
|
3995
|
+
};
|
|
3996
|
+
}
|
|
3997
|
+
/**
|
|
3998
|
+
* DEPRECATION HANDLERS - Redirect old tools to new unified system
|
|
3999
|
+
*/
|
|
4000
|
+
async handleDeprecatedWidgetDeploy(args) {
|
|
4001
|
+
const deprecationWarning = `⚠️ **DEPRECATED TOOL USED**
|
|
4002
|
+
|
|
4003
|
+
🚨 **snow_deploy_widget is deprecated** - Use \`snow_deploy\` instead
|
|
4004
|
+
|
|
4005
|
+
📋 **Automatic Redirect**: Converting to unified deployment...
|
|
4006
|
+
|
|
4007
|
+
`;
|
|
4008
|
+
// Convert old widget args to unified deploy format
|
|
4009
|
+
const unifiedArgs = {
|
|
4010
|
+
type: 'widget',
|
|
4011
|
+
config: args,
|
|
4012
|
+
auto_update_set: true,
|
|
4013
|
+
fallback_strategy: 'manual_steps'
|
|
4014
|
+
};
|
|
4015
|
+
const result = await this.unifiedDeploy(unifiedArgs);
|
|
4016
|
+
// Prepend deprecation warning to the result
|
|
4017
|
+
if (result.content && result.content[0]) {
|
|
4018
|
+
result.content[0].text = deprecationWarning + result.content[0].text;
|
|
4019
|
+
}
|
|
4020
|
+
return result;
|
|
4021
|
+
}
|
|
4022
|
+
async handleDeprecatedFlowDeploy(args) {
|
|
4023
|
+
const deprecationWarning = `⚠️ **DEPRECATED TOOL USED**
|
|
4024
|
+
|
|
4025
|
+
🚨 **snow_deploy_flow is deprecated** - Use \`snow_deploy\` instead
|
|
4026
|
+
|
|
4027
|
+
📋 **Automatic Redirect**: Converting to unified deployment...
|
|
4028
|
+
|
|
4029
|
+
`;
|
|
4030
|
+
// Convert old flow args to unified deploy format
|
|
4031
|
+
const unifiedArgs = {
|
|
4032
|
+
type: 'flow',
|
|
4033
|
+
config: args,
|
|
4034
|
+
auto_update_set: true,
|
|
4035
|
+
fallback_strategy: 'manual_steps'
|
|
4036
|
+
};
|
|
4037
|
+
const result = await this.unifiedDeploy(unifiedArgs);
|
|
4038
|
+
// Prepend deprecation warning to the result
|
|
4039
|
+
if (result.content && result.content[0]) {
|
|
4040
|
+
result.content[0].text = deprecationWarning + result.content[0].text;
|
|
4041
|
+
}
|
|
4042
|
+
return result;
|
|
4043
|
+
}
|
|
4044
|
+
async handleDeprecatedApplicationDeploy(args) {
|
|
4045
|
+
const deprecationWarning = `⚠️ **DEPRECATED TOOL USED**
|
|
4046
|
+
|
|
4047
|
+
🚨 **snow_deploy_application is deprecated** - Use \`snow_deploy\` instead
|
|
4048
|
+
|
|
4049
|
+
📋 **Automatic Redirect**: Converting to unified deployment...
|
|
4050
|
+
|
|
4051
|
+
`;
|
|
4052
|
+
// Convert old application args to unified deploy format
|
|
4053
|
+
const unifiedArgs = {
|
|
4054
|
+
type: 'application',
|
|
4055
|
+
config: args,
|
|
4056
|
+
auto_update_set: true,
|
|
4057
|
+
fallback_strategy: 'manual_steps'
|
|
4058
|
+
};
|
|
4059
|
+
const result = await this.unifiedDeploy(unifiedArgs);
|
|
4060
|
+
// Prepend deprecation warning to the result
|
|
4061
|
+
if (result.content && result.content[0]) {
|
|
4062
|
+
result.content[0].text = deprecationWarning + result.content[0].text;
|
|
4063
|
+
}
|
|
4064
|
+
return result;
|
|
4065
|
+
}
|
|
4066
|
+
async handleDeprecatedBulkDeploy(args) {
|
|
4067
|
+
const deprecationWarning = `⚠️ **DEPRECATED TOOL USED**
|
|
4068
|
+
|
|
4069
|
+
🚨 **snow_bulk_deploy is deprecated** - Use \`snow_deploy\` with batch configuration instead
|
|
4070
|
+
|
|
4071
|
+
📋 **Automatic Redirect**: Converting to unified deployment...
|
|
4072
|
+
|
|
4073
|
+
💡 **New Usage**: Use \`snow_deploy\` for single artifacts or implement batch logic with multiple \`snow_deploy\` calls
|
|
4074
|
+
|
|
4075
|
+
`;
|
|
4076
|
+
return {
|
|
4077
|
+
content: [{
|
|
4078
|
+
type: 'text',
|
|
4079
|
+
text: `${deprecationWarning}
|
|
4080
|
+
|
|
4081
|
+
❌ **Bulk Deploy No Longer Supported in Unified System**
|
|
4082
|
+
|
|
4083
|
+
🔧 **Alternative Solutions:**
|
|
4084
|
+
|
|
4085
|
+
**Option 1: Single Artifact Deployment**
|
|
4086
|
+
\`\`\`
|
|
4087
|
+
snow_deploy({
|
|
4088
|
+
type: 'widget',
|
|
4089
|
+
config: { /* your widget config */ }
|
|
4090
|
+
})
|
|
4091
|
+
\`\`\`
|
|
4092
|
+
|
|
4093
|
+
**Option 2: Multiple Sequential Deployments**
|
|
4094
|
+
Deploy each artifact individually using \`snow_deploy\` - the unified system automatically manages Update Sets across all deployments.
|
|
4095
|
+
|
|
4096
|
+
**Option 3: Use Existing Bulk Deploy (Legacy)**
|
|
4097
|
+
The original \`snow_bulk_deploy\` functionality is still available but deprecated. Consider migrating to the simplified \`snow_deploy\` approach.
|
|
4098
|
+
|
|
4099
|
+
📊 **Benefits of New Approach:**
|
|
4100
|
+
- Automatic Update Set management
|
|
4101
|
+
- Better error handling per artifact
|
|
4102
|
+
- Clearer deployment tracking
|
|
4103
|
+
- Resilient fallback strategies`
|
|
4104
|
+
}]
|
|
4105
|
+
};
|
|
4106
|
+
}
|
|
3608
4107
|
async start() {
|
|
3609
4108
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
3610
4109
|
await this.server.connect(transport);
|