@sknoble/slvsx-mcp-server 0.1.2 → 0.2.3
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/mcp-server.js +82 -69
- package/package.json +1 -1
- package/scripts/postinstall.js +9 -0
package/mcp-server.js
CHANGED
|
@@ -41,7 +41,8 @@ function findSlvsxBinary() {
|
|
|
41
41
|
// 3. Check if slvsx is in PATH
|
|
42
42
|
try {
|
|
43
43
|
const which = execSync('which slvsx 2>/dev/null || where slvsx 2>nul', { encoding: 'utf-8' }).trim();
|
|
44
|
-
|
|
44
|
+
// Handle Windows CRLF line endings by trimming each line
|
|
45
|
+
if (which) return which.split('\n')[0].trim();
|
|
45
46
|
} catch (e) {
|
|
46
47
|
// Not in PATH
|
|
47
48
|
}
|
|
@@ -440,49 +441,49 @@ class SlvsxServer {
|
|
|
440
441
|
schema: 'slvs-json/1',
|
|
441
442
|
units: 'mm',
|
|
442
443
|
entities: [
|
|
443
|
-
{
|
|
444
|
-
{
|
|
445
|
-
{
|
|
444
|
+
{ type: 'point', id: 'p1', at: [0, 0, 0] },
|
|
445
|
+
{ type: 'point', id: 'p2', at: [100, 0, 0] },
|
|
446
|
+
{ type: 'point', id: 'p3', at: [50, 86.6, 0] }
|
|
446
447
|
],
|
|
447
448
|
constraints: [
|
|
448
|
-
{ type: '
|
|
449
|
-
{ type: '
|
|
450
|
-
{ type: '
|
|
451
|
-
{ type: '
|
|
449
|
+
{ type: 'fixed', entity: 'p1' },
|
|
450
|
+
{ type: 'distance', between: ['p1', 'p2'], value: 100 },
|
|
451
|
+
{ type: 'distance', between: ['p2', 'p3'], value: 100 },
|
|
452
|
+
{ type: 'distance', between: ['p3', 'p1'], value: 100 }
|
|
452
453
|
]
|
|
453
454
|
},
|
|
454
455
|
square: {
|
|
455
456
|
schema: 'slvs-json/1',
|
|
456
457
|
units: 'mm',
|
|
457
458
|
entities: [
|
|
458
|
-
{
|
|
459
|
-
{
|
|
460
|
-
{
|
|
461
|
-
{
|
|
462
|
-
{
|
|
463
|
-
{
|
|
464
|
-
{
|
|
465
|
-
{
|
|
459
|
+
{ type: 'point', id: 'p1', at: [0, 0, 0] },
|
|
460
|
+
{ type: 'point', id: 'p2', at: [100, 0, 0] },
|
|
461
|
+
{ type: 'point', id: 'p3', at: [100, 100, 0] },
|
|
462
|
+
{ type: 'point', id: 'p4', at: [0, 100, 0] },
|
|
463
|
+
{ type: 'line', id: 'l1', p1: 'p1', p2: 'p2' },
|
|
464
|
+
{ type: 'line', id: 'l2', p1: 'p2', p2: 'p3' },
|
|
465
|
+
{ type: 'line', id: 'l3', p1: 'p3', p2: 'p4' },
|
|
466
|
+
{ type: 'line', id: 'l4', p1: 'p4', p2: 'p1' }
|
|
466
467
|
],
|
|
467
468
|
constraints: [
|
|
468
|
-
{ type: '
|
|
469
|
-
{ type: '
|
|
470
|
-
{ type: '
|
|
471
|
-
{ type: '
|
|
472
|
-
{ type: '
|
|
473
|
-
{ type: '
|
|
469
|
+
{ type: 'fixed', entity: 'p1' },
|
|
470
|
+
{ type: 'fixed', entity: 'p2' },
|
|
471
|
+
{ type: 'perpendicular', a: 'l1', b: 'l2' },
|
|
472
|
+
{ type: 'perpendicular', a: 'l2', b: 'l3' },
|
|
473
|
+
{ type: 'perpendicular', a: 'l3', b: 'l4' },
|
|
474
|
+
{ type: 'equal_length', entities: ['l1', 'l2'] }
|
|
474
475
|
]
|
|
475
476
|
},
|
|
476
477
|
circle: {
|
|
477
478
|
schema: 'slvs-json/1',
|
|
478
479
|
units: 'mm',
|
|
479
480
|
entities: [
|
|
480
|
-
{
|
|
481
|
-
{
|
|
481
|
+
{ type: 'point', id: 'center', at: [50, 50, 0] },
|
|
482
|
+
{ type: 'circle', id: 'c1', center: [50, 50, 0], diameter: 60 }
|
|
482
483
|
],
|
|
483
484
|
constraints: [
|
|
484
|
-
{ type: '
|
|
485
|
-
{ type: '
|
|
485
|
+
{ type: 'fixed', entity: 'center' },
|
|
486
|
+
{ type: 'diameter', circle: 'c1', value: 60 }
|
|
486
487
|
]
|
|
487
488
|
},
|
|
488
489
|
linkage: {
|
|
@@ -492,21 +493,20 @@ class SlvsxServer {
|
|
|
492
493
|
input_angle: 45
|
|
493
494
|
},
|
|
494
495
|
entities: [
|
|
495
|
-
{
|
|
496
|
-
{
|
|
497
|
-
{
|
|
498
|
-
{
|
|
499
|
-
{
|
|
500
|
-
{
|
|
501
|
-
{
|
|
496
|
+
{ type: 'point', id: 'ground1', at: [0, 0, 0] },
|
|
497
|
+
{ type: 'point', id: 'ground2', at: [100, 0, 0] },
|
|
498
|
+
{ type: 'point', id: 'joint1', at: [30, 30, 0] },
|
|
499
|
+
{ type: 'point', id: 'joint2', at: [70, 40, 0] },
|
|
500
|
+
{ type: 'line', id: 'link1', p1: 'ground1', p2: 'joint1' },
|
|
501
|
+
{ type: 'line', id: 'link2', p1: 'joint1', p2: 'joint2' },
|
|
502
|
+
{ type: 'line', id: 'link3', p1: 'joint2', p2: 'ground2' }
|
|
502
503
|
],
|
|
503
504
|
constraints: [
|
|
504
|
-
{ type: '
|
|
505
|
-
{ type: '
|
|
506
|
-
{ type: '
|
|
507
|
-
{ type: '
|
|
508
|
-
{ type: '
|
|
509
|
-
{ type: 'Angle', entities: ['link1'], angle: '$input_angle' }
|
|
505
|
+
{ type: 'fixed', entity: 'ground1' },
|
|
506
|
+
{ type: 'fixed', entity: 'ground2' },
|
|
507
|
+
{ type: 'distance', between: ['ground1', 'joint1'], value: 40 },
|
|
508
|
+
{ type: 'distance', between: ['joint1', 'joint2'], value: 50 },
|
|
509
|
+
{ type: 'distance', between: ['joint2', 'ground2'], value: 35 }
|
|
510
510
|
]
|
|
511
511
|
},
|
|
512
512
|
parametric: {
|
|
@@ -515,48 +515,61 @@ class SlvsxServer {
|
|
|
515
515
|
parameters: {
|
|
516
516
|
width: 150,
|
|
517
517
|
height: 100,
|
|
518
|
-
|
|
518
|
+
hole_diameter: 20
|
|
519
519
|
},
|
|
520
520
|
entities: [
|
|
521
|
-
{
|
|
522
|
-
{
|
|
523
|
-
{
|
|
524
|
-
{
|
|
525
|
-
{
|
|
526
|
-
{
|
|
521
|
+
{ type: 'point', id: 'p1', at: [0, 0, 0] },
|
|
522
|
+
{ type: 'point', id: 'p2', at: ['$width', 0, 0] },
|
|
523
|
+
{ type: 'point', id: 'p3', at: ['$width', '$height', 0] },
|
|
524
|
+
{ type: 'point', id: 'p4', at: [0, '$height', 0] },
|
|
525
|
+
{ type: 'line', id: 'bottom', p1: 'p1', p2: 'p2' },
|
|
526
|
+
{ type: 'line', id: 'right', p1: 'p2', p2: 'p3' },
|
|
527
|
+
{ type: 'line', id: 'top', p1: 'p3', p2: 'p4' },
|
|
528
|
+
{ type: 'line', id: 'left', p1: 'p4', p2: 'p1' },
|
|
529
|
+
{ type: 'circle', id: 'hole', center: [75, 50, 0], diameter: '$hole_diameter' }
|
|
527
530
|
],
|
|
528
531
|
constraints: [
|
|
529
|
-
{ type: '
|
|
530
|
-
{ type: '
|
|
531
|
-
{ type: '
|
|
532
|
-
{ type: '
|
|
533
|
-
{ type: '
|
|
534
|
-
{ type: '
|
|
532
|
+
{ type: 'fixed', entity: 'p1' },
|
|
533
|
+
{ type: 'distance', between: ['p1', 'p2'], value: '$width' },
|
|
534
|
+
{ type: 'distance', between: ['p1', 'p4'], value: '$height' },
|
|
535
|
+
{ type: 'perpendicular', a: 'bottom', b: 'right' },
|
|
536
|
+
{ type: 'perpendicular', a: 'right', b: 'top' },
|
|
537
|
+
{ type: 'diameter', circle: 'hole', value: '$hole_diameter' }
|
|
535
538
|
]
|
|
536
539
|
},
|
|
537
540
|
'3d': {
|
|
538
541
|
schema: 'slvs-json/1',
|
|
539
542
|
units: 'mm',
|
|
540
543
|
entities: [
|
|
541
|
-
{
|
|
542
|
-
{
|
|
543
|
-
{
|
|
544
|
-
{
|
|
545
|
-
{
|
|
546
|
-
{
|
|
547
|
-
{
|
|
548
|
-
{
|
|
544
|
+
{ type: 'point', id: 'p1', at: [0, 0, 0] },
|
|
545
|
+
{ type: 'point', id: 'p2', at: [100, 0, 0] },
|
|
546
|
+
{ type: 'point', id: 'p3', at: [100, 100, 0] },
|
|
547
|
+
{ type: 'point', id: 'p4', at: [0, 100, 0] },
|
|
548
|
+
{ type: 'point', id: 'p5', at: [0, 0, 50] },
|
|
549
|
+
{ type: 'point', id: 'p6', at: [100, 0, 50] },
|
|
550
|
+
{ type: 'point', id: 'p7', at: [100, 100, 50] },
|
|
551
|
+
{ type: 'point', id: 'p8', at: [0, 100, 50] },
|
|
552
|
+
{ type: 'line', id: 'base1', p1: 'p1', p2: 'p2' },
|
|
553
|
+
{ type: 'line', id: 'base2', p1: 'p2', p2: 'p3' },
|
|
554
|
+
{ type: 'line', id: 'base3', p1: 'p3', p2: 'p4' },
|
|
555
|
+
{ type: 'line', id: 'base4', p1: 'p4', p2: 'p1' },
|
|
556
|
+
{ type: 'line', id: 'top1', p1: 'p5', p2: 'p6' },
|
|
557
|
+
{ type: 'line', id: 'top2', p1: 'p6', p2: 'p7' },
|
|
558
|
+
{ type: 'line', id: 'top3', p1: 'p7', p2: 'p8' },
|
|
559
|
+
{ type: 'line', id: 'top4', p1: 'p8', p2: 'p5' },
|
|
560
|
+
{ type: 'line', id: 'vert1', p1: 'p1', p2: 'p5' },
|
|
561
|
+
{ type: 'line', id: 'vert2', p1: 'p2', p2: 'p6' },
|
|
562
|
+
{ type: 'line', id: 'vert3', p1: 'p3', p2: 'p7' },
|
|
563
|
+
{ type: 'line', id: 'vert4', p1: 'p4', p2: 'p8' }
|
|
549
564
|
],
|
|
550
565
|
constraints: [
|
|
551
|
-
{ type: '
|
|
552
|
-
{ type: '
|
|
553
|
-
{ type: '
|
|
554
|
-
{ type: '
|
|
555
|
-
{ type: '
|
|
556
|
-
{ type: '
|
|
557
|
-
{ type: '
|
|
558
|
-
{ type: 'Distance', entities: ['p3', 'p7'], distance: 50 },
|
|
559
|
-
{ type: 'Distance', entities: ['p4', 'p8'], distance: 50 }
|
|
566
|
+
{ type: 'fixed', entity: 'p1' },
|
|
567
|
+
{ type: 'fixed', entity: 'p2' },
|
|
568
|
+
{ type: 'fixed', entity: 'p4' },
|
|
569
|
+
{ type: 'distance', between: ['p1', 'p5'], value: 50 },
|
|
570
|
+
{ type: 'distance', between: ['p2', 'p6'], value: 50 },
|
|
571
|
+
{ type: 'distance', between: ['p3', 'p7'], value: 50 },
|
|
572
|
+
{ type: 'distance', between: ['p4', 'p8'], value: 50 }
|
|
560
573
|
]
|
|
561
574
|
}
|
|
562
575
|
};
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -74,16 +74,25 @@ async function downloadFile(url, dest) {
|
|
|
74
74
|
const follow = (url) => {
|
|
75
75
|
https.get(url, (res) => {
|
|
76
76
|
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
77
|
+
// Consume the redirect response to release the connection
|
|
78
|
+
res.resume();
|
|
77
79
|
follow(res.headers.location);
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
if (res.statusCode !== 200) {
|
|
84
|
+
res.resume(); // Consume response body
|
|
82
85
|
reject(new Error(`Download failed with status ${res.statusCode}`));
|
|
83
86
|
return;
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
const file = createWriteStream(dest);
|
|
90
|
+
// Handle file stream errors to prevent hanging
|
|
91
|
+
file.on('error', (err) => {
|
|
92
|
+
file.close();
|
|
93
|
+
fs.unlink(dest, () => {}); // Clean up partial file
|
|
94
|
+
reject(err);
|
|
95
|
+
});
|
|
87
96
|
res.pipe(file);
|
|
88
97
|
file.on('finish', () => {
|
|
89
98
|
file.close();
|