@alfe.ai/mcp-bundler 0.3.0 → 0.3.2
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/dist/index.cjs +169 -8
- package/dist/index.d.cts +95 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +95 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +169 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/connection.ts","../src/bundler.ts","../src/tool-naming.ts","../src/store.ts","../src/manager.ts","../src/pattern-a-validator.ts"],"mappings":";;AAIA;;;AAAkD,KAAtC,eAAA,GAAkB,iBAAoB,GAAA,kBAAA;AAAkB,UAEnD,iBAAA,CAFmD;EAEnD,OAAA,EAAA,MAAA;EAOA,IAAA,CAAA,EAAA,MAAA,EAAA;EAOL,GAAA,CAAA,EAXJ,MAWI,CAAA,MAAgB,EAAA,MAAA,CAAA;EAKX,GAAA,CAAA,EAAA,MAAA;AAejB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/connection.ts","../src/bundler.ts","../src/tool-naming.ts","../src/store.ts","../src/manager.ts","../src/pattern-a-validator.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -81,6 +81,8 @@ var Connection = class Connection {
|
|
|
81
81
|
closing = false;
|
|
82
82
|
/** Consecutive failed connect attempts — drives reconnect backoff. */
|
|
83
83
|
consecutiveFailures = 0;
|
|
84
|
+
/** Message from the most recent failed connect attempt; cleared on success. */
|
|
85
|
+
lastError;
|
|
84
86
|
/** Epoch ms before which re-connect attempts fast-fail (crash-loop guard). */
|
|
85
87
|
reconnectBlockedUntilMs = 0;
|
|
86
88
|
static RECONNECT_BACKOFF_BASE_MS = 500;
|
|
@@ -103,6 +105,18 @@ var Connection = class Connection {
|
|
|
103
105
|
isConnected() {
|
|
104
106
|
return this.client !== void 0;
|
|
105
107
|
}
|
|
108
|
+
/** Tools currently advertised; 0 until the server connects + discovers. */
|
|
109
|
+
toolCount() {
|
|
110
|
+
return this.tools.length;
|
|
111
|
+
}
|
|
112
|
+
/** Consecutive failed connect attempts; 0 when healthy. */
|
|
113
|
+
failureCount() {
|
|
114
|
+
return this.consecutiveFailures;
|
|
115
|
+
}
|
|
116
|
+
/** Message from the most recent failed connect attempt, if any. */
|
|
117
|
+
lastErrorMessage() {
|
|
118
|
+
return this.lastError;
|
|
119
|
+
}
|
|
106
120
|
/** Idle timestamp for reaping. */
|
|
107
121
|
idleSinceMs() {
|
|
108
122
|
return Date.now() - this.lastUsedAt;
|
|
@@ -126,16 +140,18 @@ var Connection = class Connection {
|
|
|
126
140
|
env: sanitizeStdioEnv(this.config.env)
|
|
127
141
|
} : this.config;
|
|
128
142
|
this.logger?.debug(`[mcp-bundler] connecting server "${this.name}"`);
|
|
129
|
-
|
|
130
|
-
serverName: this.name,
|
|
131
|
-
onStderrLine: this.onStderrLine
|
|
132
|
-
});
|
|
143
|
+
let client;
|
|
133
144
|
try {
|
|
145
|
+
client = await this.deps.connect(safeConfig, {
|
|
146
|
+
serverName: this.name,
|
|
147
|
+
onStderrLine: this.onStderrLine
|
|
148
|
+
});
|
|
134
149
|
const advertised = await client.listTools();
|
|
135
|
-
|
|
150
|
+
const connected = client;
|
|
151
|
+
this.client = connected;
|
|
136
152
|
this.closing = false;
|
|
137
|
-
|
|
138
|
-
this.handleUnexpectedClose(
|
|
153
|
+
connected.onClose?.(() => {
|
|
154
|
+
this.handleUnexpectedClose(connected);
|
|
139
155
|
});
|
|
140
156
|
this.tools = advertised.map((t) => ({
|
|
141
157
|
prefixed: buildNamespacedToolName(this.name, t.name),
|
|
@@ -147,11 +163,13 @@ var Connection = class Connection {
|
|
|
147
163
|
}));
|
|
148
164
|
this.lastUsedAt = Date.now();
|
|
149
165
|
this.consecutiveFailures = 0;
|
|
166
|
+
this.lastError = void 0;
|
|
150
167
|
this.reconnectBlockedUntilMs = 0;
|
|
151
168
|
this.logger?.info(`[mcp-bundler] server "${this.name}" connected, ${this.tools.length.toString()} tool(s)`);
|
|
152
169
|
} catch (err) {
|
|
153
|
-
await client.close().catch(() => void 0);
|
|
170
|
+
if (client) await client.close().catch(() => void 0);
|
|
154
171
|
this.consecutiveFailures += 1;
|
|
172
|
+
this.lastError = err instanceof Error ? err.message : String(err);
|
|
155
173
|
const backoff = Math.min(Connection.RECONNECT_BACKOFF_BASE_MS * 2 ** (this.consecutiveFailures - 1), Connection.RECONNECT_BACKOFF_MAX_MS);
|
|
156
174
|
this.reconnectBlockedUntilMs = Date.now() + backoff;
|
|
157
175
|
throw err;
|
|
@@ -316,6 +334,7 @@ async function defaultConnect(server, ctx) {
|
|
|
316
334
|
//#region src/bundler.ts
|
|
317
335
|
const DEFAULT_IDLE_TTL_MS = 600 * 1e3;
|
|
318
336
|
const DEFAULT_IDLE_SWEEP_INTERVAL_MS = 60 * 1e3;
|
|
337
|
+
const DEFAULT_RETRY_SWEEP_INTERVAL_MS = 60 * 1e3;
|
|
319
338
|
/** First text content of an error result, for host error reporting. */
|
|
320
339
|
function extractErrorText(result) {
|
|
321
340
|
for (const item of result.content) if (item.type === "text" && typeof item.text === "string") return item.text.slice(0, 500);
|
|
@@ -336,6 +355,9 @@ var McpBundler = class {
|
|
|
336
355
|
idleTtlMs;
|
|
337
356
|
idleSweepIntervalMs;
|
|
338
357
|
idleSweepTimer;
|
|
358
|
+
retrySweepIntervalMs;
|
|
359
|
+
retrySweepTimer;
|
|
360
|
+
retrySweepInFlight = false;
|
|
339
361
|
deps;
|
|
340
362
|
onToolError;
|
|
341
363
|
onServerCrash;
|
|
@@ -346,11 +368,13 @@ var McpBundler = class {
|
|
|
346
368
|
this.logger = opts.logger;
|
|
347
369
|
this.idleTtlMs = opts.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
|
|
348
370
|
this.idleSweepIntervalMs = opts.idleSweepIntervalMs ?? DEFAULT_IDLE_SWEEP_INTERVAL_MS;
|
|
371
|
+
this.retrySweepIntervalMs = opts.retrySweepIntervalMs ?? DEFAULT_RETRY_SWEEP_INTERVAL_MS;
|
|
349
372
|
this.deps = deps ?? { connect: defaultConnect };
|
|
350
373
|
this.onToolError = opts.onToolError;
|
|
351
374
|
this.onServerCrash = opts.onServerCrash;
|
|
352
375
|
this.onServerStderr = opts.onServerStderr;
|
|
353
376
|
if (this.idleTtlMs > 0) this.startIdleSweep();
|
|
377
|
+
if (this.retrySweepIntervalMs > 0) this.startRetrySweep();
|
|
354
378
|
}
|
|
355
379
|
/** Construct a Connection with the host hooks bound to its server name. */
|
|
356
380
|
buildConnection(name, config) {
|
|
@@ -468,6 +492,93 @@ var McpBundler = class {
|
|
|
468
492
|
}));
|
|
469
493
|
}
|
|
470
494
|
/**
|
|
495
|
+
* Re-attempt every server that is NOT connected but HAS a recorded connect
|
|
496
|
+
* failure (`connected: false && lastError`). This is the self-heal path: a
|
|
497
|
+
* server that failed its first warm — because its backing credential /
|
|
498
|
+
* account / network wasn't resolvable yet — gets reconnected once that
|
|
499
|
+
* dependency appears, WITHOUT needing an operator to restart the daemon.
|
|
500
|
+
*
|
|
501
|
+
* Convergence: this only calls `ensureConnected()`, which honours each
|
|
502
|
+
* Connection's own exponential reconnect backoff (`reconnectBlockedUntilMs`,
|
|
503
|
+
* 500ms → 30s cap). A server that keeps `exit(1)`-ing fast-fails while in
|
|
504
|
+
* backoff, so repeated sweeps are cheap and never become a tight crash-loop
|
|
505
|
+
* — the backoff widens with each failure. Servers that connect on their
|
|
506
|
+
* first warm, and lazily-added servers that never warmed (no `lastError`),
|
|
507
|
+
* are left alone.
|
|
508
|
+
*
|
|
509
|
+
* Returns the statuses of the servers it attempted (empty if none needed a
|
|
510
|
+
* retry). Never throws — per-server failures are reflected in the status.
|
|
511
|
+
*/
|
|
512
|
+
async retryFailed() {
|
|
513
|
+
if (this.disposed) return [];
|
|
514
|
+
const targets = Array.from(this.connections.values()).filter((conn) => !conn.isConnected() && conn.lastErrorMessage() !== void 0);
|
|
515
|
+
if (targets.length === 0) return [];
|
|
516
|
+
return (await Promise.allSettled(targets.map(async (conn) => {
|
|
517
|
+
try {
|
|
518
|
+
await conn.ensureConnected();
|
|
519
|
+
} catch {}
|
|
520
|
+
return this.statusOf(conn);
|
|
521
|
+
}))).flatMap((r) => r.status === "fulfilled" ? [r.value] : []);
|
|
522
|
+
}
|
|
523
|
+
/** Build the live status descriptor for one connection. */
|
|
524
|
+
statusOf(conn) {
|
|
525
|
+
const status = {
|
|
526
|
+
name: conn.name,
|
|
527
|
+
connected: conn.isConnected(),
|
|
528
|
+
toolCount: conn.toolCount(),
|
|
529
|
+
consecutiveFailures: conn.failureCount()
|
|
530
|
+
};
|
|
531
|
+
const err = conn.lastErrorMessage();
|
|
532
|
+
if (err !== void 0) status.lastError = err;
|
|
533
|
+
return status;
|
|
534
|
+
}
|
|
535
|
+
/** Live status for every known server. Synchronous snapshot, no I/O. */
|
|
536
|
+
statuses() {
|
|
537
|
+
return Array.from(this.connections.values()).map((conn) => this.statusOf(conn));
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Eagerly connect ONE server and return its resulting status. Unlike
|
|
541
|
+
* `warmup()` — which fans out over all servers and swallows failures with
|
|
542
|
+
* no return value — this surfaces the outcome so a caller (e.g. the daemon
|
|
543
|
+
* confirming an `alfe mcp add`) can report "connected, N tools" or the exact
|
|
544
|
+
* connect error back to the agent.
|
|
545
|
+
*
|
|
546
|
+
* Never throws: a connect failure (or a warm timeout) is reflected in the
|
|
547
|
+
* returned status (`connected: false`, `lastError` set). Returns `undefined`
|
|
548
|
+
* only when the named server isn't present in the bundler.
|
|
549
|
+
*/
|
|
550
|
+
async warmServer(name, timeoutMs) {
|
|
551
|
+
if (this.disposed) return void 0;
|
|
552
|
+
const conn = this.connections.get(name);
|
|
553
|
+
if (!conn) return void 0;
|
|
554
|
+
const connect = conn.ensureConnected();
|
|
555
|
+
connect.catch(() => void 0);
|
|
556
|
+
try {
|
|
557
|
+
if (timeoutMs !== void 0 && timeoutMs > 0) await this.raceTimeout(connect, timeoutMs, name);
|
|
558
|
+
else await connect;
|
|
559
|
+
} catch (err) {
|
|
560
|
+
const status = this.statusOf(conn);
|
|
561
|
+
status.lastError ??= err instanceof Error ? err.message : String(err);
|
|
562
|
+
return status;
|
|
563
|
+
}
|
|
564
|
+
return this.statusOf(conn);
|
|
565
|
+
}
|
|
566
|
+
/** Race a promise against a timeout, clearing the timer either way. */
|
|
567
|
+
async raceTimeout(p, timeoutMs, name) {
|
|
568
|
+
let timer;
|
|
569
|
+
const timeout = new Promise((_, reject) => {
|
|
570
|
+
timer = setTimeout(() => {
|
|
571
|
+
reject(/* @__PURE__ */ new Error(`server "${name}" warm timed out after ${timeoutMs.toString()}ms`));
|
|
572
|
+
}, timeoutMs);
|
|
573
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
574
|
+
});
|
|
575
|
+
try {
|
|
576
|
+
await Promise.race([p, timeout]);
|
|
577
|
+
} finally {
|
|
578
|
+
clearTimeout(timer);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
471
582
|
* Invoke a tool by its namespaced name. Routes to the originating server.
|
|
472
583
|
* Errors are returned as `{ isError: true, content: [...] }` so a failing
|
|
473
584
|
* tool doesn't crash the host.
|
|
@@ -538,6 +649,10 @@ var McpBundler = class {
|
|
|
538
649
|
clearInterval(this.idleSweepTimer);
|
|
539
650
|
this.idleSweepTimer = void 0;
|
|
540
651
|
}
|
|
652
|
+
if (this.retrySweepTimer) {
|
|
653
|
+
clearInterval(this.retrySweepTimer);
|
|
654
|
+
this.retrySweepTimer = void 0;
|
|
655
|
+
}
|
|
541
656
|
await Promise.allSettled(Array.from(this.connections.values()).map((c) => c.close()));
|
|
542
657
|
this.connections.clear();
|
|
543
658
|
}
|
|
@@ -549,6 +664,28 @@ var McpBundler = class {
|
|
|
549
664
|
}, this.idleSweepIntervalMs);
|
|
550
665
|
if (typeof this.idleSweepTimer === "object" && "unref" in this.idleSweepTimer) this.idleSweepTimer.unref();
|
|
551
666
|
}
|
|
667
|
+
startRetrySweep() {
|
|
668
|
+
this.retrySweepTimer = setInterval(() => {
|
|
669
|
+
if (this.retrySweepInFlight) return;
|
|
670
|
+
this.retrySweepInFlight = true;
|
|
671
|
+
this.retryFailed().then((attempted) => {
|
|
672
|
+
if (attempted.length === 0) return;
|
|
673
|
+
const healed = attempted.filter((s) => s.connected);
|
|
674
|
+
const stillDown = attempted.filter((s) => !s.connected);
|
|
675
|
+
this.logger?.debug("[mcp-bundler] retry sweep", {
|
|
676
|
+
attempted: attempted.length,
|
|
677
|
+
healed: healed.length,
|
|
678
|
+
stillDown: stillDown.length
|
|
679
|
+
});
|
|
680
|
+
for (const s of healed) this.logger?.info(`[mcp-bundler] server "${s.name}" self-healed on retry sweep`, { toolCount: s.toolCount });
|
|
681
|
+
}).catch((err) => {
|
|
682
|
+
this.logger?.warn("[mcp-bundler] retry sweep error", { err: err instanceof Error ? err.message : String(err) });
|
|
683
|
+
}).finally(() => {
|
|
684
|
+
this.retrySweepInFlight = false;
|
|
685
|
+
});
|
|
686
|
+
}, this.retrySweepIntervalMs);
|
|
687
|
+
if (typeof this.retrySweepTimer === "object" && "unref" in this.retrySweepTimer) this.retrySweepTimer.unref();
|
|
688
|
+
}
|
|
552
689
|
async sweepIdle() {
|
|
553
690
|
if (this.idleTtlMs <= 0) return;
|
|
554
691
|
const targets = [];
|
|
@@ -925,6 +1062,30 @@ var Manager = class {
|
|
|
925
1062
|
}));
|
|
926
1063
|
}
|
|
927
1064
|
/**
|
|
1065
|
+
* Live connection status per server from the attached bundler. Empty when
|
|
1066
|
+
* no bundler is attached (e.g. a CLI-only manager). Lets callers show
|
|
1067
|
+
* whether each registered server actually connected and how many tools it
|
|
1068
|
+
* advertises, instead of only the stored config.
|
|
1069
|
+
*/
|
|
1070
|
+
serverStatuses() {
|
|
1071
|
+
return this.bundler ? this.bundler.statuses() : [];
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Reconcile the bundler against the current store (so a just-added entry
|
|
1075
|
+
* has a connection object) then eagerly connect ONE server and return its
|
|
1076
|
+
* status. Used by the daemon to CONFIRM an `alfe mcp add` actually connected
|
|
1077
|
+
* before replying to the agent — turning the fire-and-forget warm into a
|
|
1078
|
+
* result the caller can report ("connected, N tools" or the real error).
|
|
1079
|
+
*
|
|
1080
|
+
* Returns `null` when no bundler is attached or the id isn't present; never
|
|
1081
|
+
* throws (a connect failure is carried in the returned status).
|
|
1082
|
+
*/
|
|
1083
|
+
async warmServer(id, timeoutMs) {
|
|
1084
|
+
if (!this.bundler) return null;
|
|
1085
|
+
await this.reconcileBundler();
|
|
1086
|
+
return await this.bundler.warmServer(id, timeoutMs) ?? null;
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
928
1089
|
* Push the current store contents into a bundler instance (which owns
|
|
929
1090
|
* connections / tools). Wires up a store watcher so external mutations
|
|
930
1091
|
* (e.g. another shell running `alfe mcp add`) re-reconcile.
|