@holin-work/holin-cli 1.3.4 → 1.3.6
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/holin-cli.js +52 -16
- package/package.json +1 -1
package/bin/holin-cli.js
CHANGED
|
@@ -218,10 +218,18 @@ function createProxyServer() {
|
|
|
218
218
|
|
|
219
219
|
log(`[proxy] → ${req.method} ${req.url} body=${bodyPreview}`);
|
|
220
220
|
|
|
221
|
-
//
|
|
221
|
+
// OAuth discovery probes — return standard protected-resource metadata
|
|
222
|
+
// so the host knows this MCP server requires authentication even when connected.
|
|
223
|
+
// RFC 9728: /.well-known/oauth-protected-resource must return 200 + JSON describing the auth requirement.
|
|
224
|
+
// Returning 401 here causes some hosts to show "does not require authentication".
|
|
222
225
|
if (req.url.startsWith("/.well-known/")) {
|
|
223
|
-
const body = JSON.stringify({
|
|
224
|
-
|
|
226
|
+
const body = JSON.stringify({
|
|
227
|
+
resource: `http://${PROXY_HOST}:${PROXY_PORT}`,
|
|
228
|
+
authorization_servers: [],
|
|
229
|
+
bearer_methods_supported: ["header"],
|
|
230
|
+
resource_documentation: "https://holin.work/docs/api",
|
|
231
|
+
});
|
|
232
|
+
res.writeHead(200, { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) });
|
|
225
233
|
res.end(body);
|
|
226
234
|
return;
|
|
227
235
|
}
|
|
@@ -557,10 +565,46 @@ function cmdProxyStart() {
|
|
|
557
565
|
process.on("SIGTERM", cleanupAndExit);
|
|
558
566
|
}
|
|
559
567
|
|
|
568
|
+
/**
|
|
569
|
+
* Wait until the proxy port is actually accepting TCP connections.
|
|
570
|
+
* Polls every 200ms up to `timeoutMs`. Resolves when the port is reachable,
|
|
571
|
+
* rejects on timeout.
|
|
572
|
+
*/
|
|
573
|
+
function waitForPort(port, host, timeoutMs) {
|
|
574
|
+
return new Promise((resolve, reject) => {
|
|
575
|
+
const deadline = Date.now() + timeoutMs;
|
|
576
|
+
function attempt() {
|
|
577
|
+
const req = http.get({ hostname: host, port, path: "/health", timeout: 500 }, (res) => {
|
|
578
|
+
res.resume(); // drain response body
|
|
579
|
+
req.destroy();
|
|
580
|
+
resolve();
|
|
581
|
+
});
|
|
582
|
+
req.on("error", () => {
|
|
583
|
+
req.destroy();
|
|
584
|
+
if (Date.now() >= deadline) {
|
|
585
|
+
reject(new Error(`Proxy port ${port} not reachable within ${timeoutMs}ms. Check log: ${LOG_FILE}`));
|
|
586
|
+
} else {
|
|
587
|
+
setTimeout(attempt, 200);
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
req.on("timeout", () => {
|
|
591
|
+
req.destroy();
|
|
592
|
+
if (Date.now() >= deadline) {
|
|
593
|
+
reject(new Error(`Proxy port ${port} not reachable within ${timeoutMs}ms. Check log: ${LOG_FILE}`));
|
|
594
|
+
} else {
|
|
595
|
+
setTimeout(attempt, 200);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
attempt();
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
|
|
560
603
|
function startProxyDaemon() {
|
|
561
604
|
return new Promise((resolve, reject) => {
|
|
562
605
|
if (isProxyRunning()) {
|
|
563
|
-
|
|
606
|
+
// Proxy process exists per pid file — also verify port is actually listening
|
|
607
|
+
waitForPort(PROXY_PORT, PROXY_HOST, 3000).then(resolve).catch(resolve); // best-effort
|
|
564
608
|
return;
|
|
565
609
|
}
|
|
566
610
|
|
|
@@ -574,18 +618,10 @@ function startProxyDaemon() {
|
|
|
574
618
|
|
|
575
619
|
child.unref();
|
|
576
620
|
|
|
577
|
-
//
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
if (isProxyRunning()) {
|
|
582
|
-
clearInterval(poll);
|
|
583
|
-
resolve();
|
|
584
|
-
} else if (attempts >= 15) {
|
|
585
|
-
clearInterval(poll);
|
|
586
|
-
reject(new Error(`Proxy did not start within 3s. Check log: ${LOG_FILE}`));
|
|
587
|
-
}
|
|
588
|
-
}, 200);
|
|
621
|
+
// Wait until the proxy port is actually accepting connections (up to 10s).
|
|
622
|
+
// This replaces the old pid-file poll which only confirmed the process existed,
|
|
623
|
+
// not that it was ready to serve — causing ECONNREFUSED races on slow machines.
|
|
624
|
+
waitForPort(PROXY_PORT, PROXY_HOST, 10000).then(resolve).catch(reject);
|
|
589
625
|
});
|
|
590
626
|
}
|
|
591
627
|
|