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.
- package/index.js +131 -4
- 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
|
|
20
|
-
const CURRENT_VERSION = '2.
|
|
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: '
|
|
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: '
|
|
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
|
|