mlgym-deploy 2.4.0 → 2.5.0

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 +131 -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 SECURITY FIX
20
- const CURRENT_VERSION = '2.4.0';
19
+ // Current version of this MCP server - INCREMENT FOR WORKFLOW COMPLIANCE
20
+ const CURRENT_VERSION = '2.5.0';
21
21
  const PACKAGE_NAME = 'mlgym-deploy';
22
22
 
23
23
  // Version check state
@@ -353,6 +353,99 @@ async function authenticate(args) {
353
353
  };
354
354
  }
355
355
 
356
+ // Check for existing MLGym project in current directory
357
+ async function checkExistingProject(local_path = '.') {
358
+ const absolutePath = path.resolve(local_path);
359
+
360
+ // Check for git repository
361
+ try {
362
+ const { stdout: remotes } = await execAsync('git remote -v', { cwd: absolutePath });
363
+
364
+ // Check for mlgym remote
365
+ if (remotes.includes('mlgym') && remotes.includes('git.mlgym.io')) {
366
+ // Extract project info from remote URL
367
+ const match = remotes.match(/mlgym\s+git@git\.mlgym\.io:([^\/]+)\/([^\.]+)\.git/);
368
+ if (match) {
369
+ const [, namespace, projectName] = match;
370
+ return {
371
+ exists: true,
372
+ name: projectName,
373
+ namespace: namespace,
374
+ configured: true,
375
+ message: `Project '${projectName}' already configured for MLGym deployment`
376
+ };
377
+ }
378
+ }
379
+
380
+ // Git repo exists but no mlgym remote
381
+ return {
382
+ exists: false,
383
+ has_git: true,
384
+ configured: false,
385
+ message: 'Git repository exists but no MLGym remote configured'
386
+ };
387
+ } catch {
388
+ // No git repository
389
+ return {
390
+ exists: false,
391
+ has_git: false,
392
+ configured: false,
393
+ message: 'No git repository found in current directory'
394
+ };
395
+ }
396
+ }
397
+
398
+ // Check authentication status
399
+ async function checkAuthStatus() {
400
+ const auth = await loadAuth();
401
+
402
+ if (!auth.token) {
403
+ return {
404
+ content: [{
405
+ type: 'text',
406
+ text: JSON.stringify({
407
+ status: 'not_authenticated',
408
+ message: 'No authentication found. Please use mlgym_authenticate first.',
409
+ next_step: 'Call mlgym_authenticate with email and password'
410
+ }, null, 2)
411
+ }]
412
+ };
413
+ }
414
+
415
+ // Verify token is still valid
416
+ try {
417
+ const result = await apiRequest('GET', '/api/v1/user', null, true);
418
+
419
+ if (result.success) {
420
+ return {
421
+ content: [{
422
+ type: 'text',
423
+ text: JSON.stringify({
424
+ status: 'authenticated',
425
+ email: auth.email,
426
+ message: 'Authentication valid',
427
+ user: result.data,
428
+ next_step: 'You can now use mlgym_project_init to create a project'
429
+ }, null, 2)
430
+ }]
431
+ };
432
+ }
433
+ } catch (error) {
434
+ // Token might be expired
435
+ }
436
+
437
+ return {
438
+ content: [{
439
+ type: 'text',
440
+ text: JSON.stringify({
441
+ status: 'token_expired',
442
+ message: 'Authentication token expired. Please authenticate again.',
443
+ next_step: 'Call mlgym_authenticate with email and password'
444
+ }, null, 2)
445
+ }]
446
+ };
447
+ }
448
+
356
449
  // Initialize Project (requires authentication)
357
450
  async function initProject(args) {
358
451
  let { name, description, enable_deployment = true, hostname, local_path = '.' } = args;
@@ -495,9 +588,17 @@ const server = new Server(
495
588
  server.setRequestHandler(ListToolsRequestSchema, async () => {
496
589
  return {
497
590
  tools: [
591
+ {
592
+ name: 'mlgym_auth_status',
593
+ description: 'ALWAYS CALL THIS FIRST! Check authentication status before any other operation.',
594
+ inputSchema: {
595
+ type: 'object',
596
+ properties: {}
597
+ }
598
+ },
498
599
  {
499
600
  name: 'mlgym_authenticate',
500
- description: 'Authenticate with MLGym (handles both login and account creation securely)',
601
+ description: 'PHASE 1: Authentication ONLY. Get email, password, and existing account status in ONE interaction. Never ask for project details here!',
501
602
  inputSchema: {
502
603
  type: 'object',
503
604
  properties: {
@@ -530,9 +631,23 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
530
631
  required: ['email', 'password']
531
632
  }
532
633
  },
634
+ {
635
+ name: 'mlgym_project_status',
636
+ description: 'PHASE 2 START: Check if MLGym project exists in current directory. Call this AFTER authentication succeeds.',
637
+ inputSchema: {
638
+ type: 'object',
639
+ properties: {
640
+ local_path: {
641
+ type: 'string',
642
+ description: 'Local directory path (defaults to current directory)',
643
+ default: '.'
644
+ }
645
+ }
646
+ }
647
+ },
533
648
  {
534
649
  name: 'mlgym_project_init',
535
- description: 'Initialize a project with GitLab repository and optional Coolify deployment (requires authentication)',
650
+ description: 'PHASE 2: Create project ONLY after checking project status. Never ask for email/password here - only project details!',
536
651
  inputSchema: {
537
652
  type: 'object',
538
653
  properties: {
@@ -580,9 +695,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
580
695
 
581
696
  try {
582
697
  switch (name) {
698
+ case 'mlgym_auth_status':
699
+ return await checkAuthStatus();
700
+
583
701
  case 'mlgym_authenticate':
584
702
  return await authenticate(args);
585
703
 
704
+ case 'mlgym_project_status':
705
+ const projectStatus = await checkExistingProject(args.local_path);
706
+ return {
707
+ content: [{
708
+ type: 'text',
709
+ text: JSON.stringify(projectStatus, null, 2)
710
+ }]
711
+ };
712
+
586
713
  case 'mlgym_project_init':
587
714
  return await initProject(args);
588
715
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlgym-deploy",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "MCP server for GitLab Backend - User creation and project deployment",
5
5
  "main": "index.js",
6
6
  "type": "module",