@phidiassj/aiyoperps-mcp-installer 0.6.6 → 0.6.7
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/bin/aiyoperps-mcp-installer.js +123 -9
- package/package.json +1 -1
|
@@ -147,13 +147,23 @@ async function detectClaudeCode(url) {
|
|
|
147
147
|
|
|
148
148
|
async function detectClaudeDesktop(url) {
|
|
149
149
|
const candidates = getClaudeDesktopCandidates();
|
|
150
|
-
const configPath = candidates.find(fileExists) ??
|
|
150
|
+
const configPath = candidates.find(fileExists) ??
|
|
151
|
+
candidates.find(candidate => fs.existsSync(path.dirname(candidate))) ??
|
|
152
|
+
candidates[0];
|
|
151
153
|
const exists = fileExists(configPath);
|
|
152
154
|
const parentExists = fs.existsSync(path.dirname(configPath));
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
+
const baseConfigRoot = path.dirname(path.dirname(configPath));
|
|
156
|
+
const baseRootExists = fs.existsSync(baseConfigRoot);
|
|
157
|
+
const detected = exists || parentExists || baseRootExists;
|
|
158
|
+
let supported = baseRootExists;
|
|
155
159
|
let installed = false;
|
|
156
|
-
let reason =
|
|
160
|
+
let reason = exists
|
|
161
|
+
? 'ready for JSON config merge'
|
|
162
|
+
: parentExists
|
|
163
|
+
? 'ready for JSON config merge'
|
|
164
|
+
: baseRootExists
|
|
165
|
+
? 'default config path can be created'
|
|
166
|
+
: 'config root not found';
|
|
157
167
|
|
|
158
168
|
if (exists) {
|
|
159
169
|
try {
|
|
@@ -571,9 +581,14 @@ async function resolveInstallUrl(defaultUrl, urlExplicit) {
|
|
|
571
581
|
|
|
572
582
|
stdout.write('\nProbing MCP endpoint candidates...\n');
|
|
573
583
|
for (const candidate of candidates) {
|
|
574
|
-
const
|
|
575
|
-
stdout.write(` ${ok ? 'ok' : 'fail'} ${candidate}
|
|
576
|
-
if (ok) {
|
|
584
|
+
const result = await probeMcpEndpoint(candidate);
|
|
585
|
+
stdout.write(` ${result.ok ? 'ok' : 'fail'} ${candidate}`);
|
|
586
|
+
if (!result.ok) {
|
|
587
|
+
const detail = result.stderr || result.stdout || result.error?.message || `exit=${result.status ?? 'unknown'}`;
|
|
588
|
+
stdout.write(` (${truncateText(detail, 180)})`);
|
|
589
|
+
}
|
|
590
|
+
stdout.write('\n');
|
|
591
|
+
if (result.ok) {
|
|
577
592
|
return candidate;
|
|
578
593
|
}
|
|
579
594
|
}
|
|
@@ -618,8 +633,97 @@ async function canReachMcpEndpoint(url) {
|
|
|
618
633
|
const commandLine = resolveCommandLineSpec(process.platform, url, {
|
|
619
634
|
healthCheck: true
|
|
620
635
|
});
|
|
621
|
-
|
|
622
|
-
|
|
636
|
+
return runCommand(commandLine.command, commandLine.args);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
async function probeMcpEndpoint(url) {
|
|
640
|
+
const httpResult = await probeMcpEndpointHttp(url);
|
|
641
|
+
if (!httpResult.ok) {
|
|
642
|
+
return httpResult;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (!bridgeRuntimePrepared && bridgeRuntimeAttempted) {
|
|
646
|
+
return httpResult;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const bridgeResult = await canReachMcpEndpoint(url);
|
|
650
|
+
if (!bridgeResult.ok) {
|
|
651
|
+
stdout.write(` note bridge health check failed but HTTP MCP is reachable; continuing with ${url}\n`);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return httpResult;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
async function probeMcpEndpointHttp(url) {
|
|
658
|
+
const controller = new AbortController();
|
|
659
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
660
|
+
|
|
661
|
+
try {
|
|
662
|
+
const response = await fetch(url, {
|
|
663
|
+
method: 'POST',
|
|
664
|
+
headers: {
|
|
665
|
+
'Content-Type': 'application/json'
|
|
666
|
+
},
|
|
667
|
+
body: JSON.stringify({
|
|
668
|
+
jsonrpc: '2.0',
|
|
669
|
+
id: 'installer-probe',
|
|
670
|
+
method: 'ping',
|
|
671
|
+
params: {}
|
|
672
|
+
}),
|
|
673
|
+
signal: controller.signal
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
const text = await response.text();
|
|
677
|
+
if (!response.ok) {
|
|
678
|
+
return {
|
|
679
|
+
ok: false,
|
|
680
|
+
status: response.status,
|
|
681
|
+
stdout: '',
|
|
682
|
+
stderr: `HTTP ${response.status}: ${text || response.statusText}`
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
let payload;
|
|
687
|
+
try {
|
|
688
|
+
payload = JSON.parse(text);
|
|
689
|
+
} catch (error) {
|
|
690
|
+
return {
|
|
691
|
+
ok: false,
|
|
692
|
+
status: response.status,
|
|
693
|
+
stdout: '',
|
|
694
|
+
stderr: `Invalid JSON: ${error.message}`
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if (payload?.error) {
|
|
699
|
+
return {
|
|
700
|
+
ok: false,
|
|
701
|
+
status: response.status,
|
|
702
|
+
stdout: '',
|
|
703
|
+
stderr: payload.error.message || 'JSON-RPC error'
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return {
|
|
708
|
+
ok: true,
|
|
709
|
+
status: response.status,
|
|
710
|
+
stdout: '',
|
|
711
|
+
stderr: ''
|
|
712
|
+
};
|
|
713
|
+
} catch (error) {
|
|
714
|
+
const message = error?.name === 'AbortError'
|
|
715
|
+
? 'Request timeout after 5000ms'
|
|
716
|
+
: error?.message || 'Unknown fetch error';
|
|
717
|
+
return {
|
|
718
|
+
ok: false,
|
|
719
|
+
status: null,
|
|
720
|
+
stdout: '',
|
|
721
|
+
stderr: message,
|
|
722
|
+
error
|
|
723
|
+
};
|
|
724
|
+
} finally {
|
|
725
|
+
clearTimeout(timeout);
|
|
726
|
+
}
|
|
623
727
|
}
|
|
624
728
|
|
|
625
729
|
function hasCodexBlock(content) {
|
|
@@ -802,6 +906,16 @@ function resolveCommandLineSpec(platform, url, options = {}) {
|
|
|
802
906
|
};
|
|
803
907
|
}
|
|
804
908
|
|
|
909
|
+
function truncateText(value, maxLength) {
|
|
910
|
+
if (!value) {
|
|
911
|
+
return '';
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
return value.length <= maxLength
|
|
915
|
+
? value
|
|
916
|
+
: `${value.slice(0, maxLength)}...`;
|
|
917
|
+
}
|
|
918
|
+
|
|
805
919
|
async function ensureBridgeRuntimePrepared() {
|
|
806
920
|
if (bridgeRuntimeAttempted) {
|
|
807
921
|
return bridgeRuntimePrepared;
|