mlgym-deploy 2.6.0 → 2.7.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.
Files changed (2) hide show
  1. package/index.js +147 -4
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -16,8 +16,8 @@ import crypto from 'crypto';
16
16
 
17
17
  const execAsync = promisify(exec);
18
18
 
19
- // Current version of this MCP server - INCREMENT FOR PROJECT ANALYSIS
20
- const CURRENT_VERSION = '2.6.0';
19
+ // Current version of this MCP server - INCREMENT FOR WORKFLOW FIXES
20
+ const CURRENT_VERSION = '2.7.1';
21
21
  const PACKAGE_NAME = 'mlgym-deploy';
22
22
 
23
23
  // Version check state
@@ -777,6 +777,122 @@ async function checkAuthStatus() {
777
777
  };
778
778
  }
779
779
 
780
+ // Smart deployment initialization that follows the correct workflow
781
+ async function smartDeploy(args) {
782
+ const { local_path = '.' } = args;
783
+ const absolutePath = path.resolve(local_path);
784
+
785
+ const steps = [];
786
+
787
+ try {
788
+ // Step 1: Check authentication
789
+ steps.push({ step: 'auth_check', status: 'running' });
790
+ const auth = await loadAuth();
791
+ if (!auth.token) {
792
+ steps[steps.length - 1].status = 'failed';
793
+ return {
794
+ content: [{
795
+ type: 'text',
796
+ text: JSON.stringify({
797
+ status: 'error',
798
+ message: 'Not authenticated. Please use mlgym_authenticate first',
799
+ workflow_steps: steps
800
+ }, null, 2)
801
+ }]
802
+ };
803
+ }
804
+ steps[steps.length - 1].status = 'completed';
805
+
806
+ // Step 2: Analyze project
807
+ steps.push({ step: 'project_analysis', status: 'running' });
808
+ const analysis = await analyzeProject(local_path);
809
+ steps[steps.length - 1].status = 'completed';
810
+ steps[steps.length - 1].result = {
811
+ type: analysis.project_type,
812
+ framework: analysis.framework,
813
+ suggested_name: analysis.suggested_name
814
+ };
815
+
816
+ // Step 3: Check existing project
817
+ steps.push({ step: 'check_existing', status: 'running' });
818
+ const projectStatus = await checkExistingProject(local_path);
819
+ steps[steps.length - 1].status = 'completed';
820
+
821
+ if (projectStatus.configured) {
822
+ return {
823
+ content: [{
824
+ type: 'text',
825
+ text: JSON.stringify({
826
+ status: 'info',
827
+ message: projectStatus.message,
828
+ project_name: projectStatus.name,
829
+ git_remote: `git@git.mlgym.io:${projectStatus.namespace}/${projectStatus.name}.git`,
830
+ next_steps: [
831
+ 'Project already configured',
832
+ 'Run: git push mlgym main'
833
+ ],
834
+ workflow_steps: steps
835
+ }, null, 2)
836
+ }]
837
+ };
838
+ }
839
+
840
+ // Step 4: Prepare project (generate Dockerfile if needed)
841
+ steps.push({ step: 'prepare_project', status: 'running' });
842
+ if (!analysis.has_dockerfile && analysis.project_type !== 'unknown') {
843
+ const prepResult = await prepareProject({
844
+ local_path,
845
+ project_type: analysis.project_type,
846
+ framework: analysis.framework,
847
+ package_manager: analysis.package_manager
848
+ });
849
+ steps[steps.length - 1].status = 'completed';
850
+ steps[steps.length - 1].result = prepResult.actions;
851
+ } else {
852
+ steps[steps.length - 1].status = 'skipped';
853
+ steps[steps.length - 1].result = 'Dockerfile already exists or project type unknown';
854
+ }
855
+
856
+ // Return analysis and next steps
857
+ return {
858
+ content: [{
859
+ type: 'text',
860
+ text: JSON.stringify({
861
+ status: 'ready',
862
+ message: 'Project analyzed and prepared. Ready for MLGym initialization.',
863
+ analysis: {
864
+ project_type: analysis.project_type,
865
+ framework: analysis.framework,
866
+ suggested_name: analysis.suggested_name,
867
+ has_dockerfile: analysis.has_dockerfile || true
868
+ },
869
+ next_step: 'Use mlgym_project_init with project details to create MLGym project',
870
+ suggested_params: {
871
+ name: analysis.suggested_name,
872
+ description: `${analysis.framework || analysis.project_type} application`,
873
+ enable_deployment: true,
874
+ hostname: analysis.suggested_name
875
+ },
876
+ workflow_steps: steps
877
+ }, null, 2)
878
+ }]
879
+ };
880
+
881
+ } catch (error) {
882
+ return {
883
+ content: [{
884
+ type: 'text',
885
+ text: JSON.stringify({
886
+ status: 'error',
887
+ message: 'Smart deploy failed',
888
+ error: error.message,
889
+ workflow_steps: steps
890
+ }, null, 2)
891
+ }]
892
+ };
893
+ }
894
+ }
895
+
780
896
  // Initialize Project (requires authentication)
781
897
  async function initProject(args) {
782
898
  let { name, description, enable_deployment = true, hostname, local_path = '.' } = args;
@@ -836,8 +952,18 @@ async function initProject(args) {
836
952
  enable_deployment: enable_deployment
837
953
  };
838
954
 
839
- if (enable_deployment && hostname) {
840
- projectData.hostname = hostname;
955
+ if (enable_deployment) {
956
+ // Generate a secure webhook secret for deployments
957
+ const webhookSecret = Array.from(
958
+ crypto.getRandomValues(new Uint8Array(32)),
959
+ byte => byte.toString(16).padStart(2, '0')
960
+ ).join('');
961
+
962
+ projectData.webhook_secret = webhookSecret;
963
+
964
+ if (hostname) {
965
+ projectData.hostname = hostname;
966
+ }
841
967
  }
842
968
 
843
969
  const result = await apiRequest('POST', '/api/v1/projects', projectData, true);
@@ -1057,6 +1183,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
1057
1183
  }
1058
1184
  }
1059
1185
  }
1186
+ },
1187
+ {
1188
+ name: 'mlgym_smart_deploy',
1189
+ description: 'RECOMMENDED: Smart deployment workflow that automatically analyzes, prepares, and guides you through the entire deployment process. Use this for new projects!',
1190
+ inputSchema: {
1191
+ type: 'object',
1192
+ properties: {
1193
+ local_path: {
1194
+ type: 'string',
1195
+ description: 'Local directory path (defaults to current directory)',
1196
+ default: '.'
1197
+ }
1198
+ }
1199
+ }
1060
1200
  }
1061
1201
  ]
1062
1202
  };
@@ -1106,6 +1246,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1106
1246
  }]
1107
1247
  };
1108
1248
 
1249
+ case 'mlgym_smart_deploy':
1250
+ return await smartDeploy(args);
1251
+
1109
1252
  default:
1110
1253
  throw new Error(`Unknown tool: ${name}`);
1111
1254
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlgym-deploy",
3
- "version": "2.6.0",
3
+ "version": "2.7.1",
4
4
  "description": "MCP server for GitLab Backend - User creation and project deployment",
5
5
  "main": "index.js",
6
6
  "type": "module",