@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.cjs
CHANGED
|
@@ -82,6 +82,8 @@ var Connection = class Connection {
|
|
|
82
82
|
closing = false;
|
|
83
83
|
/** Consecutive failed connect attempts — drives reconnect backoff. */
|
|
84
84
|
consecutiveFailures = 0;
|
|
85
|
+
/** Message from the most recent failed connect attempt; cleared on success. */
|
|
86
|
+
lastError;
|
|
85
87
|
/** Epoch ms before which re-connect attempts fast-fail (crash-loop guard). */
|
|
86
88
|
reconnectBlockedUntilMs = 0;
|
|
87
89
|
static RECONNECT_BACKOFF_BASE_MS = 500;
|
|
@@ -104,6 +106,18 @@ var Connection = class Connection {
|
|
|
104
106
|
isConnected() {
|
|
105
107
|
return this.client !== void 0;
|
|
106
108
|
}
|
|
109
|
+
/** Tools currently advertised; 0 until the server connects + discovers. */
|
|
110
|
+
toolCount() {
|
|
111
|
+
return this.tools.length;
|
|
112
|
+
}
|
|
113
|
+
/** Consecutive failed connect attempts; 0 when healthy. */
|
|
114
|
+
failureCount() {
|
|
115
|
+
return this.consecutiveFailures;
|
|
116
|
+
}
|
|
117
|
+
/** Message from the most recent failed connect attempt, if any. */
|
|
118
|
+
lastErrorMessage() {
|
|
119
|
+
return this.lastError;
|
|
120
|
+
}
|
|
107
121
|
/** Idle timestamp for reaping. */
|
|
108
122
|
idleSinceMs() {
|
|
109
123
|
return Date.now() - this.lastUsedAt;
|
|
@@ -127,16 +141,18 @@ var Connection = class Connection {
|
|
|
127
141
|
env: sanitizeStdioEnv(this.config.env)
|
|
128
142
|
} : this.config;
|
|
129
143
|
this.logger?.debug(`[mcp-bundler] connecting server "${this.name}"`);
|
|
130
|
-
|
|
131
|
-
serverName: this.name,
|
|
132
|
-
onStderrLine: this.onStderrLine
|
|
133
|
-
});
|
|
144
|
+
let client;
|
|
134
145
|
try {
|
|
146
|
+
client = await this.deps.connect(safeConfig, {
|
|
147
|
+
serverName: this.name,
|
|
148
|
+
onStderrLine: this.onStderrLine
|
|
149
|
+
});
|
|
135
150
|
const advertised = await client.listTools();
|
|
136
|
-
|
|
151
|
+
const connected = client;
|
|
152
|
+
this.client = connected;
|
|
137
153
|
this.closing = false;
|
|
138
|
-
|
|
139
|
-
this.handleUnexpectedClose(
|
|
154
|
+
connected.onClose?.(() => {
|
|
155
|
+
this.handleUnexpectedClose(connected);
|
|
140
156
|
});
|
|
141
157
|
this.tools = advertised.map((t) => ({
|
|
142
158
|
prefixed: buildNamespacedToolName(this.name, t.name),
|
|
@@ -148,11 +164,13 @@ var Connection = class Connection {
|
|
|
148
164
|
}));
|
|
149
165
|
this.lastUsedAt = Date.now();
|
|
150
166
|
this.consecutiveFailures = 0;
|
|
167
|
+
this.lastError = void 0;
|
|
151
168
|
this.reconnectBlockedUntilMs = 0;
|
|
152
169
|
this.logger?.info(`[mcp-bundler] server "${this.name}" connected, ${this.tools.length.toString()} tool(s)`);
|
|
153
170
|
} catch (err) {
|
|
154
|
-
await client.close().catch(() => void 0);
|
|
171
|
+
if (client) await client.close().catch(() => void 0);
|
|
155
172
|
this.consecutiveFailures += 1;
|
|
173
|
+
this.lastError = err instanceof Error ? err.message : String(err);
|
|
156
174
|
const backoff = Math.min(Connection.RECONNECT_BACKOFF_BASE_MS * 2 ** (this.consecutiveFailures - 1), Connection.RECONNECT_BACKOFF_MAX_MS);
|
|
157
175
|
this.reconnectBlockedUntilMs = Date.now() + backoff;
|
|
158
176
|
throw err;
|
|
@@ -317,6 +335,7 @@ async function defaultConnect(server, ctx) {
|
|
|
317
335
|
//#region src/bundler.ts
|
|
318
336
|
const DEFAULT_IDLE_TTL_MS = 600 * 1e3;
|
|
319
337
|
const DEFAULT_IDLE_SWEEP_INTERVAL_MS = 60 * 1e3;
|
|
338
|
+
const DEFAULT_RETRY_SWEEP_INTERVAL_MS = 60 * 1e3;
|
|
320
339
|
/** First text content of an error result, for host error reporting. */
|
|
321
340
|
function extractErrorText(result) {
|
|
322
341
|
for (const item of result.content) if (item.type === "text" && typeof item.text === "string") return item.text.slice(0, 500);
|
|
@@ -337,6 +356,9 @@ var McpBundler = class {
|
|
|
337
356
|
idleTtlMs;
|
|
338
357
|
idleSweepIntervalMs;
|
|
339
358
|
idleSweepTimer;
|
|
359
|
+
retrySweepIntervalMs;
|
|
360
|
+
retrySweepTimer;
|
|
361
|
+
retrySweepInFlight = false;
|
|
340
362
|
deps;
|
|
341
363
|
onToolError;
|
|
342
364
|
onServerCrash;
|
|
@@ -347,11 +369,13 @@ var McpBundler = class {
|
|
|
347
369
|
this.logger = opts.logger;
|
|
348
370
|
this.idleTtlMs = opts.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
|
|
349
371
|
this.idleSweepIntervalMs = opts.idleSweepIntervalMs ?? DEFAULT_IDLE_SWEEP_INTERVAL_MS;
|
|
372
|
+
this.retrySweepIntervalMs = opts.retrySweepIntervalMs ?? DEFAULT_RETRY_SWEEP_INTERVAL_MS;
|
|
350
373
|
this.deps = deps ?? { connect: defaultConnect };
|
|
351
374
|
this.onToolError = opts.onToolError;
|
|
352
375
|
this.onServerCrash = opts.onServerCrash;
|
|
353
376
|
this.onServerStderr = opts.onServerStderr;
|
|
354
377
|
if (this.idleTtlMs > 0) this.startIdleSweep();
|
|
378
|
+
if (this.retrySweepIntervalMs > 0) this.startRetrySweep();
|
|
355
379
|
}
|
|
356
380
|
/** Construct a Connection with the host hooks bound to its server name. */
|
|
357
381
|
buildConnection(name, config) {
|
|
@@ -469,6 +493,93 @@ var McpBundler = class {
|
|
|
469
493
|
}));
|
|
470
494
|
}
|
|
471
495
|
/**
|
|
496
|
+
* Re-attempt every server that is NOT connected but HAS a recorded connect
|
|
497
|
+
* failure (`connected: false && lastError`). This is the self-heal path: a
|
|
498
|
+
* server that failed its first warm — because its backing credential /
|
|
499
|
+
* account / network wasn't resolvable yet — gets reconnected once that
|
|
500
|
+
* dependency appears, WITHOUT needing an operator to restart the daemon.
|
|
501
|
+
*
|
|
502
|
+
* Convergence: this only calls `ensureConnected()`, which honours each
|
|
503
|
+
* Connection's own exponential reconnect backoff (`reconnectBlockedUntilMs`,
|
|
504
|
+
* 500ms → 30s cap). A server that keeps `exit(1)`-ing fast-fails while in
|
|
505
|
+
* backoff, so repeated sweeps are cheap and never become a tight crash-loop
|
|
506
|
+
* — the backoff widens with each failure. Servers that connect on their
|
|
507
|
+
* first warm, and lazily-added servers that never warmed (no `lastError`),
|
|
508
|
+
* are left alone.
|
|
509
|
+
*
|
|
510
|
+
* Returns the statuses of the servers it attempted (empty if none needed a
|
|
511
|
+
* retry). Never throws — per-server failures are reflected in the status.
|
|
512
|
+
*/
|
|
513
|
+
async retryFailed() {
|
|
514
|
+
if (this.disposed) return [];
|
|
515
|
+
const targets = Array.from(this.connections.values()).filter((conn) => !conn.isConnected() && conn.lastErrorMessage() !== void 0);
|
|
516
|
+
if (targets.length === 0) return [];
|
|
517
|
+
return (await Promise.allSettled(targets.map(async (conn) => {
|
|
518
|
+
try {
|
|
519
|
+
await conn.ensureConnected();
|
|
520
|
+
} catch {}
|
|
521
|
+
return this.statusOf(conn);
|
|
522
|
+
}))).flatMap((r) => r.status === "fulfilled" ? [r.value] : []);
|
|
523
|
+
}
|
|
524
|
+
/** Build the live status descriptor for one connection. */
|
|
525
|
+
statusOf(conn) {
|
|
526
|
+
const status = {
|
|
527
|
+
name: conn.name,
|
|
528
|
+
connected: conn.isConnected(),
|
|
529
|
+
toolCount: conn.toolCount(),
|
|
530
|
+
consecutiveFailures: conn.failureCount()
|
|
531
|
+
};
|
|
532
|
+
const err = conn.lastErrorMessage();
|
|
533
|
+
if (err !== void 0) status.lastError = err;
|
|
534
|
+
return status;
|
|
535
|
+
}
|
|
536
|
+
/** Live status for every known server. Synchronous snapshot, no I/O. */
|
|
537
|
+
statuses() {
|
|
538
|
+
return Array.from(this.connections.values()).map((conn) => this.statusOf(conn));
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Eagerly connect ONE server and return its resulting status. Unlike
|
|
542
|
+
* `warmup()` — which fans out over all servers and swallows failures with
|
|
543
|
+
* no return value — this surfaces the outcome so a caller (e.g. the daemon
|
|
544
|
+
* confirming an `alfe mcp add`) can report "connected, N tools" or the exact
|
|
545
|
+
* connect error back to the agent.
|
|
546
|
+
*
|
|
547
|
+
* Never throws: a connect failure (or a warm timeout) is reflected in the
|
|
548
|
+
* returned status (`connected: false`, `lastError` set). Returns `undefined`
|
|
549
|
+
* only when the named server isn't present in the bundler.
|
|
550
|
+
*/
|
|
551
|
+
async warmServer(name, timeoutMs) {
|
|
552
|
+
if (this.disposed) return void 0;
|
|
553
|
+
const conn = this.connections.get(name);
|
|
554
|
+
if (!conn) return void 0;
|
|
555
|
+
const connect = conn.ensureConnected();
|
|
556
|
+
connect.catch(() => void 0);
|
|
557
|
+
try {
|
|
558
|
+
if (timeoutMs !== void 0 && timeoutMs > 0) await this.raceTimeout(connect, timeoutMs, name);
|
|
559
|
+
else await connect;
|
|
560
|
+
} catch (err) {
|
|
561
|
+
const status = this.statusOf(conn);
|
|
562
|
+
status.lastError ??= err instanceof Error ? err.message : String(err);
|
|
563
|
+
return status;
|
|
564
|
+
}
|
|
565
|
+
return this.statusOf(conn);
|
|
566
|
+
}
|
|
567
|
+
/** Race a promise against a timeout, clearing the timer either way. */
|
|
568
|
+
async raceTimeout(p, timeoutMs, name) {
|
|
569
|
+
let timer;
|
|
570
|
+
const timeout = new Promise((_, reject) => {
|
|
571
|
+
timer = setTimeout(() => {
|
|
572
|
+
reject(/* @__PURE__ */ new Error(`server "${name}" warm timed out after ${timeoutMs.toString()}ms`));
|
|
573
|
+
}, timeoutMs);
|
|
574
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
575
|
+
});
|
|
576
|
+
try {
|
|
577
|
+
await Promise.race([p, timeout]);
|
|
578
|
+
} finally {
|
|
579
|
+
clearTimeout(timer);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
472
583
|
* Invoke a tool by its namespaced name. Routes to the originating server.
|
|
473
584
|
* Errors are returned as `{ isError: true, content: [...] }` so a failing
|
|
474
585
|
* tool doesn't crash the host.
|
|
@@ -539,6 +650,10 @@ var McpBundler = class {
|
|
|
539
650
|
clearInterval(this.idleSweepTimer);
|
|
540
651
|
this.idleSweepTimer = void 0;
|
|
541
652
|
}
|
|
653
|
+
if (this.retrySweepTimer) {
|
|
654
|
+
clearInterval(this.retrySweepTimer);
|
|
655
|
+
this.retrySweepTimer = void 0;
|
|
656
|
+
}
|
|
542
657
|
await Promise.allSettled(Array.from(this.connections.values()).map((c) => c.close()));
|
|
543
658
|
this.connections.clear();
|
|
544
659
|
}
|
|
@@ -550,6 +665,28 @@ var McpBundler = class {
|
|
|
550
665
|
}, this.idleSweepIntervalMs);
|
|
551
666
|
if (typeof this.idleSweepTimer === "object" && "unref" in this.idleSweepTimer) this.idleSweepTimer.unref();
|
|
552
667
|
}
|
|
668
|
+
startRetrySweep() {
|
|
669
|
+
this.retrySweepTimer = setInterval(() => {
|
|
670
|
+
if (this.retrySweepInFlight) return;
|
|
671
|
+
this.retrySweepInFlight = true;
|
|
672
|
+
this.retryFailed().then((attempted) => {
|
|
673
|
+
if (attempted.length === 0) return;
|
|
674
|
+
const healed = attempted.filter((s) => s.connected);
|
|
675
|
+
const stillDown = attempted.filter((s) => !s.connected);
|
|
676
|
+
this.logger?.debug("[mcp-bundler] retry sweep", {
|
|
677
|
+
attempted: attempted.length,
|
|
678
|
+
healed: healed.length,
|
|
679
|
+
stillDown: stillDown.length
|
|
680
|
+
});
|
|
681
|
+
for (const s of healed) this.logger?.info(`[mcp-bundler] server "${s.name}" self-healed on retry sweep`, { toolCount: s.toolCount });
|
|
682
|
+
}).catch((err) => {
|
|
683
|
+
this.logger?.warn("[mcp-bundler] retry sweep error", { err: err instanceof Error ? err.message : String(err) });
|
|
684
|
+
}).finally(() => {
|
|
685
|
+
this.retrySweepInFlight = false;
|
|
686
|
+
});
|
|
687
|
+
}, this.retrySweepIntervalMs);
|
|
688
|
+
if (typeof this.retrySweepTimer === "object" && "unref" in this.retrySweepTimer) this.retrySweepTimer.unref();
|
|
689
|
+
}
|
|
553
690
|
async sweepIdle() {
|
|
554
691
|
if (this.idleTtlMs <= 0) return;
|
|
555
692
|
const targets = [];
|
|
@@ -926,6 +1063,30 @@ var Manager = class {
|
|
|
926
1063
|
}));
|
|
927
1064
|
}
|
|
928
1065
|
/**
|
|
1066
|
+
* Live connection status per server from the attached bundler. Empty when
|
|
1067
|
+
* no bundler is attached (e.g. a CLI-only manager). Lets callers show
|
|
1068
|
+
* whether each registered server actually connected and how many tools it
|
|
1069
|
+
* advertises, instead of only the stored config.
|
|
1070
|
+
*/
|
|
1071
|
+
serverStatuses() {
|
|
1072
|
+
return this.bundler ? this.bundler.statuses() : [];
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Reconcile the bundler against the current store (so a just-added entry
|
|
1076
|
+
* has a connection object) then eagerly connect ONE server and return its
|
|
1077
|
+
* status. Used by the daemon to CONFIRM an `alfe mcp add` actually connected
|
|
1078
|
+
* before replying to the agent — turning the fire-and-forget warm into a
|
|
1079
|
+
* result the caller can report ("connected, N tools" or the real error).
|
|
1080
|
+
*
|
|
1081
|
+
* Returns `null` when no bundler is attached or the id isn't present; never
|
|
1082
|
+
* throws (a connect failure is carried in the returned status).
|
|
1083
|
+
*/
|
|
1084
|
+
async warmServer(id, timeoutMs) {
|
|
1085
|
+
if (!this.bundler) return null;
|
|
1086
|
+
await this.reconcileBundler();
|
|
1087
|
+
return await this.bundler.warmServer(id, timeoutMs) ?? null;
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
929
1090
|
* Push the current store contents into a bundler instance (which owns
|
|
930
1091
|
* connections / tools). Wires up a store watcher so external mutations
|
|
931
1092
|
* (e.g. another shell running `alfe mcp add`) re-reconcile.
|
package/dist/index.d.cts
CHANGED
|
@@ -40,6 +40,24 @@ interface ReconcileDiff {
|
|
|
40
40
|
changed: string[];
|
|
41
41
|
unchanged: string[];
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Live connection status for one MCP server in the bundler. Surfaced so a
|
|
45
|
+
* host can report whether a server actually connected and how many tools it
|
|
46
|
+
* advertises — e.g. the daemon confirming an `alfe mcp add` before replying
|
|
47
|
+
* to the agent, rather than optimistically claiming tools will appear.
|
|
48
|
+
*/
|
|
49
|
+
interface McpServerStatus {
|
|
50
|
+
/** Server name (store key). */
|
|
51
|
+
name: string;
|
|
52
|
+
/** Whether a child process / remote connection is currently established. */
|
|
53
|
+
connected: boolean;
|
|
54
|
+
/** Tools currently advertised (0 until the server connects + discovers). */
|
|
55
|
+
toolCount: number;
|
|
56
|
+
/** Consecutive failed connect attempts; 0 when healthy. */
|
|
57
|
+
consecutiveFailures: number;
|
|
58
|
+
/** Message from the most recent failed connect attempt, if any. */
|
|
59
|
+
lastError?: string;
|
|
60
|
+
}
|
|
43
61
|
interface Logger {
|
|
44
62
|
debug: (msg: string, meta?: Record<string, unknown>) => void;
|
|
45
63
|
info: (msg: string, meta?: Record<string, unknown>) => void;
|
|
@@ -74,6 +92,15 @@ interface BundlerOptions {
|
|
|
74
92
|
idleTtlMs?: number;
|
|
75
93
|
/** Sweep interval for idle reaping (ms). Default: 60_000 (1 min). */
|
|
76
94
|
idleSweepIntervalMs?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Sweep interval for re-attempting servers that failed to connect
|
|
97
|
+
* (`connected: false && lastError`), so a server whose backing
|
|
98
|
+
* credential/account/network appears AFTER the first warm self-heals without
|
|
99
|
+
* an operator restart (ms). 0 disables. Default: 60_000 (1 min). The
|
|
100
|
+
* fine-grained backoff still lives on each Connection — this is the coarse
|
|
101
|
+
* outer bound that keeps re-checking.
|
|
102
|
+
*/
|
|
103
|
+
retrySweepIntervalMs?: number;
|
|
77
104
|
/**
|
|
78
105
|
* Host hook fired when a tool call fails — thrown or `isError` result.
|
|
79
106
|
* Invoked best-effort (exceptions swallowed); must not block.
|
|
@@ -156,6 +183,8 @@ declare class Connection {
|
|
|
156
183
|
private closing;
|
|
157
184
|
/** Consecutive failed connect attempts — drives reconnect backoff. */
|
|
158
185
|
private consecutiveFailures;
|
|
186
|
+
/** Message from the most recent failed connect attempt; cleared on success. */
|
|
187
|
+
private lastError;
|
|
159
188
|
/** Epoch ms before which re-connect attempts fast-fail (crash-loop guard). */
|
|
160
189
|
private reconnectBlockedUntilMs;
|
|
161
190
|
private static readonly RECONNECT_BACKOFF_BASE_MS;
|
|
@@ -176,6 +205,12 @@ declare class Connection {
|
|
|
176
205
|
snapshotTools(): McpToolDescriptor[];
|
|
177
206
|
/** Whether an MCP child process / remote connection has been established. */
|
|
178
207
|
isConnected(): boolean;
|
|
208
|
+
/** Tools currently advertised; 0 until the server connects + discovers. */
|
|
209
|
+
toolCount(): number;
|
|
210
|
+
/** Consecutive failed connect attempts; 0 when healthy. */
|
|
211
|
+
failureCount(): number;
|
|
212
|
+
/** Message from the most recent failed connect attempt, if any. */
|
|
213
|
+
lastErrorMessage(): string | undefined;
|
|
179
214
|
/** Idle timestamp for reaping. */
|
|
180
215
|
idleSinceMs(): number;
|
|
181
216
|
/**
|
|
@@ -233,6 +268,9 @@ declare class McpBundler {
|
|
|
233
268
|
private readonly idleTtlMs;
|
|
234
269
|
private readonly idleSweepIntervalMs;
|
|
235
270
|
private idleSweepTimer;
|
|
271
|
+
private readonly retrySweepIntervalMs;
|
|
272
|
+
private retrySweepTimer;
|
|
273
|
+
private retrySweepInFlight;
|
|
236
274
|
private readonly deps;
|
|
237
275
|
private readonly onToolError;
|
|
238
276
|
private readonly onServerCrash;
|
|
@@ -270,6 +308,43 @@ declare class McpBundler {
|
|
|
270
308
|
* swallowed per-server (logged), so one bad server doesn't fail the batch.
|
|
271
309
|
*/
|
|
272
310
|
warmup(): Promise<void>;
|
|
311
|
+
/**
|
|
312
|
+
* Re-attempt every server that is NOT connected but HAS a recorded connect
|
|
313
|
+
* failure (`connected: false && lastError`). This is the self-heal path: a
|
|
314
|
+
* server that failed its first warm — because its backing credential /
|
|
315
|
+
* account / network wasn't resolvable yet — gets reconnected once that
|
|
316
|
+
* dependency appears, WITHOUT needing an operator to restart the daemon.
|
|
317
|
+
*
|
|
318
|
+
* Convergence: this only calls `ensureConnected()`, which honours each
|
|
319
|
+
* Connection's own exponential reconnect backoff (`reconnectBlockedUntilMs`,
|
|
320
|
+
* 500ms → 30s cap). A server that keeps `exit(1)`-ing fast-fails while in
|
|
321
|
+
* backoff, so repeated sweeps are cheap and never become a tight crash-loop
|
|
322
|
+
* — the backoff widens with each failure. Servers that connect on their
|
|
323
|
+
* first warm, and lazily-added servers that never warmed (no `lastError`),
|
|
324
|
+
* are left alone.
|
|
325
|
+
*
|
|
326
|
+
* Returns the statuses of the servers it attempted (empty if none needed a
|
|
327
|
+
* retry). Never throws — per-server failures are reflected in the status.
|
|
328
|
+
*/
|
|
329
|
+
retryFailed(): Promise<McpServerStatus[]>;
|
|
330
|
+
/** Build the live status descriptor for one connection. */
|
|
331
|
+
private statusOf;
|
|
332
|
+
/** Live status for every known server. Synchronous snapshot, no I/O. */
|
|
333
|
+
statuses(): McpServerStatus[];
|
|
334
|
+
/**
|
|
335
|
+
* Eagerly connect ONE server and return its resulting status. Unlike
|
|
336
|
+
* `warmup()` — which fans out over all servers and swallows failures with
|
|
337
|
+
* no return value — this surfaces the outcome so a caller (e.g. the daemon
|
|
338
|
+
* confirming an `alfe mcp add`) can report "connected, N tools" or the exact
|
|
339
|
+
* connect error back to the agent.
|
|
340
|
+
*
|
|
341
|
+
* Never throws: a connect failure (or a warm timeout) is reflected in the
|
|
342
|
+
* returned status (`connected: false`, `lastError` set). Returns `undefined`
|
|
343
|
+
* only when the named server isn't present in the bundler.
|
|
344
|
+
*/
|
|
345
|
+
warmServer(name: string, timeoutMs?: number): Promise<McpServerStatus | undefined>;
|
|
346
|
+
/** Race a promise against a timeout, clearing the timer either way. */
|
|
347
|
+
private raceTimeout;
|
|
273
348
|
/**
|
|
274
349
|
* Invoke a tool by its namespaced name. Routes to the originating server.
|
|
275
350
|
* Errors are returned as `{ isError: true, content: [...] }` so a failing
|
|
@@ -287,6 +362,7 @@ declare class McpBundler {
|
|
|
287
362
|
*/
|
|
288
363
|
dispose(): Promise<void>;
|
|
289
364
|
private startIdleSweep;
|
|
365
|
+
private startRetrySweep;
|
|
290
366
|
private sweepIdle;
|
|
291
367
|
}
|
|
292
368
|
//# sourceMappingURL=bundler.d.ts.map
|
|
@@ -488,6 +564,24 @@ declare class Manager {
|
|
|
488
564
|
id: string;
|
|
489
565
|
entry: StoredServerEntry;
|
|
490
566
|
}[];
|
|
567
|
+
/**
|
|
568
|
+
* Live connection status per server from the attached bundler. Empty when
|
|
569
|
+
* no bundler is attached (e.g. a CLI-only manager). Lets callers show
|
|
570
|
+
* whether each registered server actually connected and how many tools it
|
|
571
|
+
* advertises, instead of only the stored config.
|
|
572
|
+
*/
|
|
573
|
+
serverStatuses(): McpServerStatus[];
|
|
574
|
+
/**
|
|
575
|
+
* Reconcile the bundler against the current store (so a just-added entry
|
|
576
|
+
* has a connection object) then eagerly connect ONE server and return its
|
|
577
|
+
* status. Used by the daemon to CONFIRM an `alfe mcp add` actually connected
|
|
578
|
+
* before replying to the agent — turning the fire-and-forget warm into a
|
|
579
|
+
* result the caller can report ("connected, N tools" or the real error).
|
|
580
|
+
*
|
|
581
|
+
* Returns `null` when no bundler is attached or the id isn't present; never
|
|
582
|
+
* throws (a connect failure is carried in the returned status).
|
|
583
|
+
*/
|
|
584
|
+
warmServer(id: string, timeoutMs?: number): Promise<McpServerStatus | null>;
|
|
491
585
|
/**
|
|
492
586
|
* Push the current store contents into a bundler instance (which owns
|
|
493
587
|
* connections / tools). Wires up a store watcher so external mutations
|
|
@@ -567,5 +661,5 @@ declare function fromMcpDescriptor(descriptor: McpToolDescriptor): ValidatableTo
|
|
|
567
661
|
//# sourceMappingURL=pattern-a-validator.d.ts.map
|
|
568
662
|
|
|
569
663
|
//#endregion
|
|
570
|
-
export { type AddServerOptions, type BundlerOptions, type ConnectContext, Connection, type ConnectionDeps, type Logger, Manager, type ManagerOptions, McpBundler, type McpClientHandle, type McpServerConfig, type McpToolCallResult, type McpToolDescriptor, type McpToolErrorInfo, type McpTransportKind, type PatternAOptions, type PatternAViolation, type ReconcileDiff, type RemoteServerConfig, STDIO_ENV_DENYLIST, type ServerOwner, type StdioServerConfig, Store, type StoreOptions, type StoreSchema, type StoredServerEntry, type ValidatableTool, assertPatternA, buildNamespacedToolName, checkPatternA, defaultConnect, defaultStorePath, disambiguateAgainst, fromMcpDescriptor, sanitizeNameSegment, sanitizeStdioEnv, toServerConfig, toStoredEntry };
|
|
664
|
+
export { type AddServerOptions, type BundlerOptions, type ConnectContext, Connection, type ConnectionDeps, type Logger, Manager, type ManagerOptions, McpBundler, type McpClientHandle, type McpServerConfig, type McpServerStatus, type McpToolCallResult, type McpToolDescriptor, type McpToolErrorInfo, type McpTransportKind, type PatternAOptions, type PatternAViolation, type ReconcileDiff, type RemoteServerConfig, STDIO_ENV_DENYLIST, type ServerOwner, type StdioServerConfig, Store, type StoreOptions, type StoreSchema, type StoredServerEntry, type ValidatableTool, assertPatternA, buildNamespacedToolName, checkPatternA, defaultConnect, defaultStorePath, disambiguateAgainst, fromMcpDescriptor, sanitizeNameSegment, sanitizeStdioEnv, toServerConfig, toStoredEntry };
|
|
571
665
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","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.cts","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.d.ts
CHANGED
|
@@ -40,6 +40,24 @@ interface ReconcileDiff {
|
|
|
40
40
|
changed: string[];
|
|
41
41
|
unchanged: string[];
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Live connection status for one MCP server in the bundler. Surfaced so a
|
|
45
|
+
* host can report whether a server actually connected and how many tools it
|
|
46
|
+
* advertises — e.g. the daemon confirming an `alfe mcp add` before replying
|
|
47
|
+
* to the agent, rather than optimistically claiming tools will appear.
|
|
48
|
+
*/
|
|
49
|
+
interface McpServerStatus {
|
|
50
|
+
/** Server name (store key). */
|
|
51
|
+
name: string;
|
|
52
|
+
/** Whether a child process / remote connection is currently established. */
|
|
53
|
+
connected: boolean;
|
|
54
|
+
/** Tools currently advertised (0 until the server connects + discovers). */
|
|
55
|
+
toolCount: number;
|
|
56
|
+
/** Consecutive failed connect attempts; 0 when healthy. */
|
|
57
|
+
consecutiveFailures: number;
|
|
58
|
+
/** Message from the most recent failed connect attempt, if any. */
|
|
59
|
+
lastError?: string;
|
|
60
|
+
}
|
|
43
61
|
interface Logger {
|
|
44
62
|
debug: (msg: string, meta?: Record<string, unknown>) => void;
|
|
45
63
|
info: (msg: string, meta?: Record<string, unknown>) => void;
|
|
@@ -74,6 +92,15 @@ interface BundlerOptions {
|
|
|
74
92
|
idleTtlMs?: number;
|
|
75
93
|
/** Sweep interval for idle reaping (ms). Default: 60_000 (1 min). */
|
|
76
94
|
idleSweepIntervalMs?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Sweep interval for re-attempting servers that failed to connect
|
|
97
|
+
* (`connected: false && lastError`), so a server whose backing
|
|
98
|
+
* credential/account/network appears AFTER the first warm self-heals without
|
|
99
|
+
* an operator restart (ms). 0 disables. Default: 60_000 (1 min). The
|
|
100
|
+
* fine-grained backoff still lives on each Connection — this is the coarse
|
|
101
|
+
* outer bound that keeps re-checking.
|
|
102
|
+
*/
|
|
103
|
+
retrySweepIntervalMs?: number;
|
|
77
104
|
/**
|
|
78
105
|
* Host hook fired when a tool call fails — thrown or `isError` result.
|
|
79
106
|
* Invoked best-effort (exceptions swallowed); must not block.
|
|
@@ -156,6 +183,8 @@ declare class Connection {
|
|
|
156
183
|
private closing;
|
|
157
184
|
/** Consecutive failed connect attempts — drives reconnect backoff. */
|
|
158
185
|
private consecutiveFailures;
|
|
186
|
+
/** Message from the most recent failed connect attempt; cleared on success. */
|
|
187
|
+
private lastError;
|
|
159
188
|
/** Epoch ms before which re-connect attempts fast-fail (crash-loop guard). */
|
|
160
189
|
private reconnectBlockedUntilMs;
|
|
161
190
|
private static readonly RECONNECT_BACKOFF_BASE_MS;
|
|
@@ -176,6 +205,12 @@ declare class Connection {
|
|
|
176
205
|
snapshotTools(): McpToolDescriptor[];
|
|
177
206
|
/** Whether an MCP child process / remote connection has been established. */
|
|
178
207
|
isConnected(): boolean;
|
|
208
|
+
/** Tools currently advertised; 0 until the server connects + discovers. */
|
|
209
|
+
toolCount(): number;
|
|
210
|
+
/** Consecutive failed connect attempts; 0 when healthy. */
|
|
211
|
+
failureCount(): number;
|
|
212
|
+
/** Message from the most recent failed connect attempt, if any. */
|
|
213
|
+
lastErrorMessage(): string | undefined;
|
|
179
214
|
/** Idle timestamp for reaping. */
|
|
180
215
|
idleSinceMs(): number;
|
|
181
216
|
/**
|
|
@@ -233,6 +268,9 @@ declare class McpBundler {
|
|
|
233
268
|
private readonly idleTtlMs;
|
|
234
269
|
private readonly idleSweepIntervalMs;
|
|
235
270
|
private idleSweepTimer;
|
|
271
|
+
private readonly retrySweepIntervalMs;
|
|
272
|
+
private retrySweepTimer;
|
|
273
|
+
private retrySweepInFlight;
|
|
236
274
|
private readonly deps;
|
|
237
275
|
private readonly onToolError;
|
|
238
276
|
private readonly onServerCrash;
|
|
@@ -270,6 +308,43 @@ declare class McpBundler {
|
|
|
270
308
|
* swallowed per-server (logged), so one bad server doesn't fail the batch.
|
|
271
309
|
*/
|
|
272
310
|
warmup(): Promise<void>;
|
|
311
|
+
/**
|
|
312
|
+
* Re-attempt every server that is NOT connected but HAS a recorded connect
|
|
313
|
+
* failure (`connected: false && lastError`). This is the self-heal path: a
|
|
314
|
+
* server that failed its first warm — because its backing credential /
|
|
315
|
+
* account / network wasn't resolvable yet — gets reconnected once that
|
|
316
|
+
* dependency appears, WITHOUT needing an operator to restart the daemon.
|
|
317
|
+
*
|
|
318
|
+
* Convergence: this only calls `ensureConnected()`, which honours each
|
|
319
|
+
* Connection's own exponential reconnect backoff (`reconnectBlockedUntilMs`,
|
|
320
|
+
* 500ms → 30s cap). A server that keeps `exit(1)`-ing fast-fails while in
|
|
321
|
+
* backoff, so repeated sweeps are cheap and never become a tight crash-loop
|
|
322
|
+
* — the backoff widens with each failure. Servers that connect on their
|
|
323
|
+
* first warm, and lazily-added servers that never warmed (no `lastError`),
|
|
324
|
+
* are left alone.
|
|
325
|
+
*
|
|
326
|
+
* Returns the statuses of the servers it attempted (empty if none needed a
|
|
327
|
+
* retry). Never throws — per-server failures are reflected in the status.
|
|
328
|
+
*/
|
|
329
|
+
retryFailed(): Promise<McpServerStatus[]>;
|
|
330
|
+
/** Build the live status descriptor for one connection. */
|
|
331
|
+
private statusOf;
|
|
332
|
+
/** Live status for every known server. Synchronous snapshot, no I/O. */
|
|
333
|
+
statuses(): McpServerStatus[];
|
|
334
|
+
/**
|
|
335
|
+
* Eagerly connect ONE server and return its resulting status. Unlike
|
|
336
|
+
* `warmup()` — which fans out over all servers and swallows failures with
|
|
337
|
+
* no return value — this surfaces the outcome so a caller (e.g. the daemon
|
|
338
|
+
* confirming an `alfe mcp add`) can report "connected, N tools" or the exact
|
|
339
|
+
* connect error back to the agent.
|
|
340
|
+
*
|
|
341
|
+
* Never throws: a connect failure (or a warm timeout) is reflected in the
|
|
342
|
+
* returned status (`connected: false`, `lastError` set). Returns `undefined`
|
|
343
|
+
* only when the named server isn't present in the bundler.
|
|
344
|
+
*/
|
|
345
|
+
warmServer(name: string, timeoutMs?: number): Promise<McpServerStatus | undefined>;
|
|
346
|
+
/** Race a promise against a timeout, clearing the timer either way. */
|
|
347
|
+
private raceTimeout;
|
|
273
348
|
/**
|
|
274
349
|
* Invoke a tool by its namespaced name. Routes to the originating server.
|
|
275
350
|
* Errors are returned as `{ isError: true, content: [...] }` so a failing
|
|
@@ -287,6 +362,7 @@ declare class McpBundler {
|
|
|
287
362
|
*/
|
|
288
363
|
dispose(): Promise<void>;
|
|
289
364
|
private startIdleSweep;
|
|
365
|
+
private startRetrySweep;
|
|
290
366
|
private sweepIdle;
|
|
291
367
|
}
|
|
292
368
|
//# sourceMappingURL=bundler.d.ts.map
|
|
@@ -488,6 +564,24 @@ declare class Manager {
|
|
|
488
564
|
id: string;
|
|
489
565
|
entry: StoredServerEntry;
|
|
490
566
|
}[];
|
|
567
|
+
/**
|
|
568
|
+
* Live connection status per server from the attached bundler. Empty when
|
|
569
|
+
* no bundler is attached (e.g. a CLI-only manager). Lets callers show
|
|
570
|
+
* whether each registered server actually connected and how many tools it
|
|
571
|
+
* advertises, instead of only the stored config.
|
|
572
|
+
*/
|
|
573
|
+
serverStatuses(): McpServerStatus[];
|
|
574
|
+
/**
|
|
575
|
+
* Reconcile the bundler against the current store (so a just-added entry
|
|
576
|
+
* has a connection object) then eagerly connect ONE server and return its
|
|
577
|
+
* status. Used by the daemon to CONFIRM an `alfe mcp add` actually connected
|
|
578
|
+
* before replying to the agent — turning the fire-and-forget warm into a
|
|
579
|
+
* result the caller can report ("connected, N tools" or the real error).
|
|
580
|
+
*
|
|
581
|
+
* Returns `null` when no bundler is attached or the id isn't present; never
|
|
582
|
+
* throws (a connect failure is carried in the returned status).
|
|
583
|
+
*/
|
|
584
|
+
warmServer(id: string, timeoutMs?: number): Promise<McpServerStatus | null>;
|
|
491
585
|
/**
|
|
492
586
|
* Push the current store contents into a bundler instance (which owns
|
|
493
587
|
* connections / tools). Wires up a store watcher so external mutations
|
|
@@ -567,5 +661,5 @@ declare function fromMcpDescriptor(descriptor: McpToolDescriptor): ValidatableTo
|
|
|
567
661
|
//# sourceMappingURL=pattern-a-validator.d.ts.map
|
|
568
662
|
|
|
569
663
|
//#endregion
|
|
570
|
-
export { type AddServerOptions, type BundlerOptions, type ConnectContext, Connection, type ConnectionDeps, type Logger, Manager, type ManagerOptions, McpBundler, type McpClientHandle, type McpServerConfig, type McpToolCallResult, type McpToolDescriptor, type McpToolErrorInfo, type McpTransportKind, type PatternAOptions, type PatternAViolation, type ReconcileDiff, type RemoteServerConfig, STDIO_ENV_DENYLIST, type ServerOwner, type StdioServerConfig, Store, type StoreOptions, type StoreSchema, type StoredServerEntry, type ValidatableTool, assertPatternA, buildNamespacedToolName, checkPatternA, defaultConnect, defaultStorePath, disambiguateAgainst, fromMcpDescriptor, sanitizeNameSegment, sanitizeStdioEnv, toServerConfig, toStoredEntry };
|
|
664
|
+
export { type AddServerOptions, type BundlerOptions, type ConnectContext, Connection, type ConnectionDeps, type Logger, Manager, type ManagerOptions, McpBundler, type McpClientHandle, type McpServerConfig, type McpServerStatus, type McpToolCallResult, type McpToolDescriptor, type McpToolErrorInfo, type McpTransportKind, type PatternAOptions, type PatternAViolation, type ReconcileDiff, type RemoteServerConfig, STDIO_ENV_DENYLIST, type ServerOwner, type StdioServerConfig, Store, type StoreOptions, type StoreSchema, type StoredServerEntry, type ValidatableTool, assertPatternA, buildNamespacedToolName, checkPatternA, defaultConnect, defaultStorePath, disambiguateAgainst, fromMcpDescriptor, sanitizeNameSegment, sanitizeStdioEnv, toServerConfig, toStoredEntry };
|
|
571
665
|
//# sourceMappingURL=index.d.ts.map
|