mlgym-deploy 3.0.0 → 3.0.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 +245 -2
  2. package/package.json +11 -3
package/index.js CHANGED
@@ -17,7 +17,7 @@ import crypto from 'crypto';
17
17
  const execAsync = promisify(exec);
18
18
 
19
19
  // Current version of this MCP server - INCREMENT FOR WORKFLOW FIXES
20
- const CURRENT_VERSION = '3.0.0'; // Monolithic workflow: reduced AI complexity, server-side orchestration
20
+ const CURRENT_VERSION = '3.0.1'; // Restored legacy user creation and login tools
21
21
  const PACKAGE_NAME = 'mlgym-deploy';
22
22
 
23
23
  // Version check state
@@ -1107,6 +1107,193 @@ async function initProject(args) {
1107
1107
  };
1108
1108
  }
1109
1109
 
1110
+ // ============================================================================
1111
+ // LEGACY USER MANAGEMENT TOOLS (DISABLED - kept for reference)
1112
+ // ============================================================================
1113
+
1114
+ // Create User (from v2.3.0 - ENABLED)
1115
+ async function createUser(args) {
1116
+ let { email, name, password, accept_terms } = args;
1117
+
1118
+ // Validate all required fields
1119
+ if (!email || !name || !password || accept_terms !== true) {
1120
+ return {
1121
+ content: [{
1122
+ type: 'text',
1123
+ text: JSON.stringify({
1124
+ status: 'error',
1125
+ message: 'All fields are required: email, name, password, and accept_terms must be true',
1126
+ required_fields: {
1127
+ email: email ? '✓ provided' : '✗ missing',
1128
+ name: name ? '✓ provided' : '✗ missing',
1129
+ password: password ? '✓ provided' : '✗ missing',
1130
+ accept_terms: accept_terms === true ? '✓ accepted' : '✗ must explicitly accept terms'
1131
+ }
1132
+ }, null, 2)
1133
+ }]
1134
+ };
1135
+ }
1136
+
1137
+ console.error(`Creating user: ${email}`);
1138
+
1139
+ try {
1140
+ // Generate SSH key pair
1141
+ console.error('Generating SSH key pair...');
1142
+ const { publicKey, privateKeyPath } = await generateSSHKeyPair(email);
1143
+ const publicKeyPath = privateKeyPath + '.pub';
1144
+ console.error(`SSH key generated: ${privateKeyPath}`);
1145
+
1146
+ // Create user via backend API with SSH key
1147
+ const result = await apiRequest('POST', '/api/v1/users', {
1148
+ email,
1149
+ name,
1150
+ password,
1151
+ ssh_key: publicKey
1152
+ }, false);
1153
+
1154
+ if (!result.success) {
1155
+ return {
1156
+ content: [{
1157
+ type: 'text',
1158
+ text: `Failed to create user: ${result.error}`
1159
+ }]
1160
+ };
1161
+ }
1162
+
1163
+ // Save authentication token
1164
+ if (result.data.token) {
1165
+ await saveAuth(email, result.data.token);
1166
+ }
1167
+
1168
+ const userData = result.data.user || {};
1169
+ const sshKeyStatus = result.data.ssh_key_status || 'Unknown';
1170
+ const sshKeyUploaded = sshKeyStatus === 'SSH key uploaded successfully';
1171
+
1172
+ const nextSteps = [
1173
+ 'Using your provided password',
1174
+ `SSH key generated locally at: ${privateKeyPath}`
1175
+ ];
1176
+
1177
+ if (sshKeyUploaded) {
1178
+ nextSteps.push(`✅ SSH key uploaded to GitLab (ID: ${result.data.ssh_key_id || 'unknown'})`);
1179
+ nextSteps.push(`Add to SSH agent: ssh-add "${privateKeyPath}"`);
1180
+ nextSteps.push('You can now push code to GitLab repositories');
1181
+ } else {
1182
+ nextSteps.push(`⚠️ SSH key upload failed: ${sshKeyStatus}`);
1183
+ nextSteps.push('You need to manually add the SSH key to GitLab:');
1184
+ nextSteps.push(`cat ${publicKeyPath} # Copy this key`);
1185
+ nextSteps.push('Then add it at: https://git.mlgym.io/-/user_settings/ssh_keys');
1186
+ }
1187
+
1188
+ const response = {
1189
+ user_id: userData.user_id || userData.UserID,
1190
+ email: userData.email || email,
1191
+ name: userData.name || name,
1192
+ gitlab_username: userData.gitlab_username || userData.GitLabUsername,
1193
+ ssh_key_path: privateKeyPath,
1194
+ ssh_key_status: sshKeyStatus,
1195
+ ssh_key_uploaded: sshKeyUploaded,
1196
+ token: result.data.token,
1197
+ message: result.data.message || 'User created successfully',
1198
+ next_steps: nextSteps
1199
+ };
1200
+
1201
+ return {
1202
+ content: [{
1203
+ type: 'text',
1204
+ text: JSON.stringify(response, null, 2)
1205
+ }]
1206
+ };
1207
+ } catch (error) {
1208
+ return {
1209
+ content: [{
1210
+ type: 'text',
1211
+ text: `Failed to create user: ${error.message}`
1212
+ }]
1213
+ };
1214
+ }
1215
+ }
1216
+
1217
+ // Login User (from v2.3.0 - ENABLED)
1218
+ async function loginUser(args) {
1219
+ const { email, password } = args;
1220
+
1221
+ if (!email || !password) {
1222
+ return {
1223
+ content: [{
1224
+ type: 'text',
1225
+ text: JSON.stringify({
1226
+ status: 'error',
1227
+ message: 'Email and password are required'
1228
+ }, null, 2)
1229
+ }]
1230
+ };
1231
+ }
1232
+
1233
+ console.error(`Logging in user: ${email}`);
1234
+
1235
+ try {
1236
+ const result = await apiRequest('POST', '/api/v1/auth/login', {
1237
+ email,
1238
+ password
1239
+ }, false);
1240
+
1241
+ if (!result.success) {
1242
+ return {
1243
+ content: [{
1244
+ type: 'text',
1245
+ text: JSON.stringify({
1246
+ status: 'error',
1247
+ message: result.error || 'Login failed',
1248
+ details: 'Invalid email or password'
1249
+ }, null, 2)
1250
+ }]
1251
+ };
1252
+ }
1253
+
1254
+ // Save authentication token
1255
+ if (result.data.token) {
1256
+ await saveAuth(email, result.data.token);
1257
+ }
1258
+
1259
+ const userData = result.data.user || {};
1260
+ const response = {
1261
+ status: 'success',
1262
+ token: result.data.token,
1263
+ user: {
1264
+ user_id: userData.user_id || userData.UserID,
1265
+ email: userData.email || email,
1266
+ name: userData.name || userData.Name,
1267
+ gitlab_username: userData.gitlab_username || userData.GitLabUsername
1268
+ },
1269
+ expires_at: result.data.expires_at || new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
1270
+ message: 'Login successful',
1271
+ next_steps: [
1272
+ 'You can now create and manage projects',
1273
+ 'Use mlgym_project_init or mlgym_deploy to create a new project',
1274
+ 'Token will expire in 24 hours'
1275
+ ]
1276
+ };
1277
+
1278
+ return {
1279
+ content: [{
1280
+ type: 'text',
1281
+ text: JSON.stringify(response, null, 2)
1282
+ }]
1283
+ };
1284
+ } catch (error) {
1285
+ return {
1286
+ content: [{
1287
+ type: 'text',
1288
+ text: JSON.stringify({
1289
+ status: 'error',
1290
+ message: `Login failed: ${error.message}`
1291
+ }, null, 2)
1292
+ }]
1293
+ };
1294
+ }
1295
+ }
1296
+
1110
1297
  // ============================================================================
1111
1298
  // MONOLITHIC DEPLOYMENT WORKFLOW CLASS (v3.0.0)
1112
1299
  // ============================================================================
@@ -1533,6 +1720,56 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
1533
1720
  }
1534
1721
  }
1535
1722
  }
1723
+ },
1724
+ // ========== LEGACY TOOLS (Re-enabled for specific use cases) ==========
1725
+ {
1726
+ name: 'mlgym_user_create',
1727
+ description: 'Create a new MLGym user account. All fields required: email, name, password, and accept_terms=true.',
1728
+ inputSchema: {
1729
+ type: 'object',
1730
+ properties: {
1731
+ email: {
1732
+ type: 'string',
1733
+ description: 'User email address',
1734
+ pattern: '^[^@]+@[^@]+\\.[^@]+$'
1735
+ },
1736
+ name: {
1737
+ type: 'string',
1738
+ description: 'User full name',
1739
+ minLength: 2
1740
+ },
1741
+ password: {
1742
+ type: 'string',
1743
+ description: 'User password (minimum 8 characters)',
1744
+ minLength: 8
1745
+ },
1746
+ accept_terms: {
1747
+ type: 'boolean',
1748
+ description: 'User must explicitly accept terms and conditions (must be true)'
1749
+ }
1750
+ },
1751
+ required: ['email', 'name', 'password', 'accept_terms']
1752
+ }
1753
+ },
1754
+ {
1755
+ name: 'mlgym_auth_login',
1756
+ description: 'Login with existing user credentials to get authentication token.',
1757
+ inputSchema: {
1758
+ type: 'object',
1759
+ properties: {
1760
+ email: {
1761
+ type: 'string',
1762
+ description: 'Email address',
1763
+ pattern: '^[^@]+@[^@]+\\.[^@]+$'
1764
+ },
1765
+ password: {
1766
+ type: 'string',
1767
+ description: 'Password',
1768
+ minLength: 8
1769
+ }
1770
+ },
1771
+ required: ['email', 'password']
1772
+ }
1536
1773
  }
1537
1774
  ]
1538
1775
  };
@@ -1552,8 +1789,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1552
1789
  case 'mlgym_status':
1553
1790
  return await getStatus(args);
1554
1791
 
1792
+ case 'mlgym_user_create':
1793
+ return await createUser(args);
1794
+
1795
+ case 'mlgym_auth_login':
1796
+ return await loginUser(args);
1797
+
1555
1798
  default:
1556
- throw new Error(`Unknown tool: ${name}. Available tools: mlgym_deploy, mlgym_status`);
1799
+ throw new Error(`Unknown tool: ${name}. Available tools: mlgym_deploy, mlgym_status, mlgym_user_create, mlgym_auth_login`);
1557
1800
  }
1558
1801
  } catch (error) {
1559
1802
  console.error(`Tool execution failed:`, error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mlgym-deploy",
3
- "version": "3.0.0",
4
- "description": "MCP server for MLGym - Monolithic deployment workflow with reduced AI complexity",
3
+ "version": "3.0.1",
4
+ "description": "MCP server for MLGym - Monolithic deployment workflow with legacy user management tools restored",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "bin": {
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "mcp": {
32
32
  "name": "MLGym Deploy",
33
- "description": "Deploy applications to MLGym with monolithic server-side workflows - just 2 tools",
33
+ "description": "Deploy applications to MLGym with monolithic workflows plus legacy user management",
34
34
  "tools": [
35
35
  {
36
36
  "name": "mlgym_deploy",
@@ -39,6 +39,14 @@
39
39
  {
40
40
  "name": "mlgym_status",
41
41
  "description": "Check authentication and project configuration status"
42
+ },
43
+ {
44
+ "name": "mlgym_user_create",
45
+ "description": "Create new MLGym user account with SSH key setup"
46
+ },
47
+ {
48
+ "name": "mlgym_auth_login",
49
+ "description": "Login with existing credentials"
42
50
  }
43
51
  ]
44
52
  }