@gethelio/proxy 0.1.0 → 0.1.1

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.
@@ -6,7 +6,7 @@
6
6
  <meta name="referrer" content="no-referrer" />
7
7
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
8
8
  <title>Helio Dashboard</title>
9
- <script type="module" crossorigin src="/assets/index-Yyo92yXC.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-CAgnN6wV.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="/assets/index-DG3h7Cvn.css">
11
11
  </head>
12
12
  <body>
package/dist/index.js CHANGED
@@ -1092,6 +1092,45 @@ async function parseUpstreamResponse(res) {
1092
1092
  return { status: res.status, headers, body };
1093
1093
  }
1094
1094
 
1095
+ // src/upstream/connection-error.ts
1096
+ var UPSTREAM_DOCS_URL = "https://github.com/gethelio/helio/blob/main/docs/getting-started.md";
1097
+ var UNREACHABLE_CODES = /* @__PURE__ */ new Set([
1098
+ "ECONNREFUSED",
1099
+ "ENOTFOUND",
1100
+ "EAI_AGAIN",
1101
+ "ECONNRESET",
1102
+ "EHOSTUNREACH",
1103
+ "ENETUNREACH",
1104
+ "ETIMEDOUT",
1105
+ "EPIPE",
1106
+ "UND_ERR_CONNECT_TIMEOUT",
1107
+ "UND_ERR_SOCKET"
1108
+ ]);
1109
+ function extractErrorCode(error) {
1110
+ let current = error;
1111
+ for (let depth = 0; depth < 5 && current != null; depth += 1) {
1112
+ if (typeof current === "object" && "code" in current) {
1113
+ const code = current.code;
1114
+ if (typeof code === "string") return code;
1115
+ }
1116
+ current = current.cause;
1117
+ }
1118
+ return void 0;
1119
+ }
1120
+ function describeUnreachableUpstream(error, url) {
1121
+ const code = extractErrorCode(error);
1122
+ const isGenericFetchFailure = error instanceof TypeError && error.message === "fetch failed";
1123
+ if (code !== void 0) {
1124
+ if (!UNREACHABLE_CODES.has(code)) return null;
1125
+ } else if (!isGenericFetchFailure) {
1126
+ return null;
1127
+ }
1128
+ const codeSuffix = code ? ` (${code})` : "";
1129
+ return new Error(
1130
+ `Upstream MCP server at ${url} is unreachable${codeSuffix} \u2014 is it running? Helio proxies an existing MCP server: set upstream.url in helio.yaml to a reachable server, or start the server it points at. See ${UPSTREAM_DOCS_URL}`
1131
+ );
1132
+ }
1133
+
1095
1134
  // src/upstream/forwarder.ts
1096
1135
  var UpstreamForwarder = class {
1097
1136
  url;
@@ -1139,7 +1178,7 @@ var UpstreamForwarder = class {
1139
1178
  if (isTimeout) {
1140
1179
  throw new Error(`upstream request timed out after ${String(this.requestTimeoutMs)}ms`);
1141
1180
  }
1142
- throw error;
1181
+ throw describeUnreachableUpstream(error, this.url) ?? error;
1143
1182
  }
1144
1183
  const durationMs = performance.now() - start;
1145
1184
  const contentType = res.headers.get("content-type") ?? "";
@@ -1300,7 +1339,7 @@ var SseUpstreamForwarder = class {
1300
1339
  );
1301
1340
  return;
1302
1341
  }
1303
- reject(asError);
1342
+ reject(describeUnreachableUpstream(err, this.url) ?? asError);
1304
1343
  }
1305
1344
  });
1306
1345
  });
@@ -1346,7 +1385,7 @@ var SseUpstreamForwarder = class {
1346
1385
  `upstream notification POST timed out after ${String(this.requestTimeoutMs)}ms`
1347
1386
  );
1348
1387
  }
1349
- throw asError;
1388
+ throw describeUnreachableUpstream(error, this.postUrl) ?? asError;
1350
1389
  }
1351
1390
  if (!res.ok) {
1352
1391
  throw new Error(`upstream notification POST failed: HTTP ${String(res.status)}`);
@@ -1393,7 +1432,8 @@ var SseUpstreamForwarder = class {
1393
1432
  const asError = error instanceof Error ? error : new Error(String(error));
1394
1433
  const isTimeout = asError.name === "TimeoutError";
1395
1434
  const isAborted = request.signal?.aborted === true;
1396
- const postFailure = isTimeout ? new Error(`upstream request POST timed out after ${String(this.requestTimeoutMs)}ms`) : asError;
1435
+ const networkFailure = describeUnreachableUpstream(error, this.postUrl) ?? asError;
1436
+ const postFailure = isTimeout ? new Error(`upstream request POST timed out after ${String(this.requestTimeoutMs)}ms`) : networkFailure;
1397
1437
  this.pending.reject(
1398
1438
  requestId,
1399
1439
  isAborted ? new Error("request aborted by downstream client") : postFailure
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethelio/proxy",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Open-source MCP governance proxy for AI agents",
6
6
  "license": "Apache-2.0",
@@ -32,6 +32,19 @@
32
32
  "types": "./dist/index.d.ts"
33
33
  }
34
34
  },
35
+ "scripts": {
36
+ "dev": "tsup --watch",
37
+ "build:dashboard": "pnpm --filter @gethelio/dashboard build",
38
+ "build:proxy": "tsup",
39
+ "bundle:dashboard-assets": "tsx scripts/bundle-dashboard-assets.ts",
40
+ "check:dashboard-assets": "tsx scripts/check-dashboard-assets.ts",
41
+ "build": "pnpm run build:dashboard && pnpm run build:proxy && pnpm run bundle:dashboard-assets && pnpm run check:dashboard-assets",
42
+ "test": "vitest run",
43
+ "test:watch": "vitest",
44
+ "typecheck": "tsc --noEmit",
45
+ "benchmark": "tsx scripts/benchmark.ts",
46
+ "prepack": "pnpm run check:dashboard-assets"
47
+ },
35
48
  "devDependencies": {
36
49
  "@modelcontextprotocol/sdk": "1.28.0",
37
50
  "@types/better-sqlite3": "7.6.13",
@@ -40,7 +53,7 @@
40
53
  "@types/picomatch": "4.0.2",
41
54
  "tsup": "8.5.1",
42
55
  "tsx": "4.21.0",
43
- "vitest": "3.2.4"
56
+ "vitest": "4.1.8"
44
57
  },
45
58
  "dependencies": {
46
59
  "@hono/node-server": "1.19.13",
@@ -53,17 +66,5 @@
53
66
  "picomatch": "4.0.4",
54
67
  "safe-regex2": "5.0.0",
55
68
  "zod": "4.3.6"
56
- },
57
- "scripts": {
58
- "dev": "tsup --watch",
59
- "build:dashboard": "pnpm --filter @gethelio/dashboard build",
60
- "build:proxy": "tsup",
61
- "bundle:dashboard-assets": "tsx scripts/bundle-dashboard-assets.ts",
62
- "check:dashboard-assets": "tsx scripts/check-dashboard-assets.ts",
63
- "build": "pnpm run build:dashboard && pnpm run build:proxy && pnpm run bundle:dashboard-assets && pnpm run check:dashboard-assets",
64
- "test": "vitest run",
65
- "test:watch": "vitest",
66
- "typecheck": "tsc --noEmit",
67
- "benchmark": "tsx scripts/benchmark.ts"
68
69
  }
69
- }
70
+ }