@anchrd/intel-api 0.12.2 → 0.12.4

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.
@@ -64,9 +64,38 @@ export function createTools(deps) {
64
64
  await deps.tokens.write(who.connectionOf, refreshed);
65
65
  return refreshed.accessToken;
66
66
  }
67
+ /**
68
+ * ⚠️ Whatever the portal answers, the caller hears which side is at fault — never a bare 500.
69
+ *
70
+ * Measured against the live installation (#308): adding ONE server to the portal made
71
+ * `/api/v1/tools` answer `500 internal_error`, and with it every tool of every OTHER server
72
+ * disappeared — an empty tools screen, an agent profile that can offer nothing, and no hint
73
+ * anywhere which of the four servers caused it. The failure is total by nature (there is one
74
+ * `tools/list` for the whole portal, and the MCP client either parses it or does not), but the
75
+ * SILENCE was ours: the throw travelled up unhandled.
76
+ *
77
+ * `tool_catalog_unreadable` is therefore not a nicer word for the same outage. It is the
78
+ * difference between "Intel is broken" and "the portal answered something Intel could not read,
79
+ * and the reason is in the log" — the same rule `adapters/json-schema` learned the hard way in
80
+ * #229, where a catch-all that renamed the failure hid it for weeks.
81
+ */
67
82
  async function remoteTools(who) {
68
83
  const token = await accessToken(who);
69
- const remote = await deps.remote.list(portal(), token, AbortSignal.timeout(CallTimeoutMs));
84
+ const remote = await deps.remote
85
+ .list(portal(), token, AbortSignal.timeout(CallTimeoutMs))
86
+ .catch((error) => {
87
+ // An IntelError on this path is a decision somebody already made (an expired sign-in, a
88
+ // refusal). Renaming it would throw away the one message that names the actual cause.
89
+ if (error instanceof IntelError)
90
+ throw error;
91
+ reportUnexpectedError(error);
92
+ // ⚠️ Deliberately says nothing about WHY. This one catch covers a portal that answered
93
+ // something unparseable, a portal that did not answer at all (the deadline above), and a
94
+ // portal that refused — and a message naming one of them would be wrong for the other two.
95
+ // That is the #229 mistake in miniature: a sentence more specific than the evidence sends
96
+ // the reader looking in the wrong place. The evidence is in the log.
97
+ throw new IntelError(502, "tool_catalog_unreadable", "The MCP portal's tool list could not be read; the reason was logged");
98
+ });
70
99
  if (remote.length > MaxTools) {
71
100
  throw new IntelError(502, "tool_catalog_too_large", "The portal returned too many tools");
72
101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anchrd/intel-api",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@anchrd/gate-sdk": "^0.7.0",
46
- "@anchrd/intel-contract": "^0.9.0",
46
+ "@anchrd/intel-contract": "^0.10.0",
47
47
  "@cfworker/json-schema": "^4.1.1",
48
48
  "@modelcontextprotocol/sdk": "^1.30.0",
49
49
  "fflate": "^0.8.3",