@alfe.ai/mcp-bundler 0.4.1 → 0.4.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 +10 -4
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1481,7 +1481,10 @@ var Manager = class {
|
|
|
1481
1481
|
}
|
|
1482
1482
|
};
|
|
1483
1483
|
});
|
|
1484
|
-
if (
|
|
1484
|
+
if (opts.strictReconcile) {
|
|
1485
|
+
await this.reconcileBundler();
|
|
1486
|
+
this.fireChange();
|
|
1487
|
+
} else if (await this.reconcileBundlerLogged()) this.fireChange();
|
|
1485
1488
|
}
|
|
1486
1489
|
/**
|
|
1487
1490
|
* Remove a single server entry. No-op if the id isn't in the store.
|
|
@@ -1502,9 +1505,12 @@ var Manager = class {
|
|
|
1502
1505
|
servers: Object.fromEntries(Object.entries(cur.servers).filter(([key]) => key !== id))
|
|
1503
1506
|
};
|
|
1504
1507
|
});
|
|
1505
|
-
if (!outcome.removed) return false;
|
|
1506
|
-
if (
|
|
1507
|
-
|
|
1508
|
+
if (!outcome.removed && !opts.strictReconcile) return false;
|
|
1509
|
+
if (opts.strictReconcile) {
|
|
1510
|
+
await this.reconcileBundler();
|
|
1511
|
+
this.fireChange();
|
|
1512
|
+
} else if (await this.reconcileBundlerLogged()) this.fireChange();
|
|
1513
|
+
return outcome.removed;
|
|
1508
1514
|
}
|
|
1509
1515
|
/** Drop every entry whose owner matches — used by integration uninstall. */
|
|
1510
1516
|
async removeServersByOwner(owner) {
|
package/dist/index.d.cts
CHANGED
|
@@ -572,6 +572,8 @@ interface AddServerOptions {
|
|
|
572
572
|
version?: string;
|
|
573
573
|
/** Explicit transport hint for remote configs. Defaults to inferring from `config`. */
|
|
574
574
|
transport?: McpTransportKind;
|
|
575
|
+
/** Propagate live replacement errors when the caller owns a retryable authority checkpoint. */
|
|
576
|
+
strictReconcile?: boolean;
|
|
575
577
|
}
|
|
576
578
|
/**
|
|
577
579
|
* Bundler manager — owns the `~/.alfe/mcp/servers.json` store and surfaces a
|
|
@@ -616,6 +618,7 @@ declare class Manager {
|
|
|
616
618
|
*/
|
|
617
619
|
removeServer(id: string, opts?: {
|
|
618
620
|
expectedOwner?: ServerOwner;
|
|
621
|
+
strictReconcile?: boolean;
|
|
619
622
|
}): Promise<boolean>;
|
|
620
623
|
/** Drop every entry whose owner matches — used by integration uninstall. */
|
|
621
624
|
removeServersByOwner(owner: ServerOwner): Promise<string[]>;
|
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":"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
|
|
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
|
@@ -572,6 +572,8 @@ interface AddServerOptions {
|
|
|
572
572
|
version?: string;
|
|
573
573
|
/** Explicit transport hint for remote configs. Defaults to inferring from `config`. */
|
|
574
574
|
transport?: McpTransportKind;
|
|
575
|
+
/** Propagate live replacement errors when the caller owns a retryable authority checkpoint. */
|
|
576
|
+
strictReconcile?: boolean;
|
|
575
577
|
}
|
|
576
578
|
/**
|
|
577
579
|
* Bundler manager — owns the `~/.alfe/mcp/servers.json` store and surfaces a
|
|
@@ -616,6 +618,7 @@ declare class Manager {
|
|
|
616
618
|
*/
|
|
617
619
|
removeServer(id: string, opts?: {
|
|
618
620
|
expectedOwner?: ServerOwner;
|
|
621
|
+
strictReconcile?: boolean;
|
|
619
622
|
}): Promise<boolean>;
|
|
620
623
|
/** Drop every entry whose owner matches — used by integration uninstall. */
|
|
621
624
|
removeServersByOwner(owner: ServerOwner): Promise<string[]>;
|
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":"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
|
|
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
|
@@ -1480,7 +1480,10 @@ var Manager = class {
|
|
|
1480
1480
|
}
|
|
1481
1481
|
};
|
|
1482
1482
|
});
|
|
1483
|
-
if (
|
|
1483
|
+
if (opts.strictReconcile) {
|
|
1484
|
+
await this.reconcileBundler();
|
|
1485
|
+
this.fireChange();
|
|
1486
|
+
} else if (await this.reconcileBundlerLogged()) this.fireChange();
|
|
1484
1487
|
}
|
|
1485
1488
|
/**
|
|
1486
1489
|
* Remove a single server entry. No-op if the id isn't in the store.
|
|
@@ -1501,9 +1504,12 @@ var Manager = class {
|
|
|
1501
1504
|
servers: Object.fromEntries(Object.entries(cur.servers).filter(([key]) => key !== id))
|
|
1502
1505
|
};
|
|
1503
1506
|
});
|
|
1504
|
-
if (!outcome.removed) return false;
|
|
1505
|
-
if (
|
|
1506
|
-
|
|
1507
|
+
if (!outcome.removed && !opts.strictReconcile) return false;
|
|
1508
|
+
if (opts.strictReconcile) {
|
|
1509
|
+
await this.reconcileBundler();
|
|
1510
|
+
this.fireChange();
|
|
1511
|
+
} else if (await this.reconcileBundlerLogged()) this.fireChange();
|
|
1512
|
+
return outcome.removed;
|
|
1507
1513
|
}
|
|
1508
1514
|
/** Drop every entry whose owner matches — used by integration uninstall. */
|
|
1509
1515
|
async removeServersByOwner(owner) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isRecord","errMsg"],"sources":["../src/tool-naming.ts","../src/validation.ts","../src/connection.ts","../src/bundler.ts","../src/store.ts","../src/manager.ts","../src/pattern-a-validator.ts"],"sourcesContent":["/**\n * Tool name sanitization and collision handling.\n *\n * OpenClaw constraint: tool names must match `[A-Za-z0-9_-]` and be ≤64 chars.\n * Pattern mirrored from `openclaw/src/agents/pi-bundle-mcp-names.ts`.\n *\n * Strategy: prefix every tool with its server name (`{server}__{tool}`),\n * sanitize disallowed chars to `_`, truncate, then suffix-disambiguate\n * (`-2`, `-3`, ...) on collision.\n */\n\nconst DISALLOWED = /[^A-Za-z0-9_-]/g;\nconst MAX_LEN = 64;\nconst SEPARATOR = '__';\n\nexport function sanitizeNameSegment(value: string): string {\n return value.replace(DISALLOWED, '_');\n}\n\nexport function buildNamespacedToolName(server: string, tool: string): string {\n const sanitizedServer = sanitizeNameSegment(server);\n const sanitizedTool = sanitizeNameSegment(tool);\n const serverBudget = MAX_LEN - SEPARATOR.length - 1;\n const boundedServer = sanitizedServer.slice(0, serverBudget);\n const base = `${boundedServer}${SEPARATOR}${sanitizedTool}`;\n if (base.length <= MAX_LEN) return base;\n // Truncate from the tool side first to keep the server prefix intact.\n const reservedForServer = boundedServer.length + SEPARATOR.length;\n const toolBudget = Math.max(1, MAX_LEN - reservedForServer);\n return `${boundedServer}${SEPARATOR}${sanitizedTool.slice(0, toolBudget)}`;\n}\n\n/**\n * Disambiguate a candidate name against an existing set by appending `-2`, `-3`, etc.\n * Mutates nothing; returns the chosen name. Caller is responsible for inserting it\n * into the set.\n */\nexport function disambiguateAgainst(candidate: string, taken: ReadonlySet<string>): string {\n if (!taken.has(candidate)) return candidate;\n // At most `taken.size` candidate names can be occupied, so this bound is\n // guaranteed to find a free suffix without returning a second collision.\n for (let i = 2; i <= taken.size + 2; i += 1) {\n const suffix = `-${i.toString()}`;\n const room = MAX_LEN - suffix.length;\n const trimmed = candidate.length > room ? candidate.slice(0, room) : candidate;\n const next = `${trimmed}${suffix}`;\n if (!taken.has(next)) return next;\n }\n throw new Error('unable to disambiguate MCP tool name');\n}\n","import { isAbsolute } from 'node:path';\nimport type {\n McpServerConfig,\n McpToolCallResult,\n McpToolDescriptor,\n RemoteServerConfig,\n StdioServerConfig,\n} from './types.js';\nimport { buildNamespacedToolName } from './tool-naming.js';\n\nconst MAX_SERVERS = 256;\nconst MAX_TOOLS_PER_SERVER = 512;\nconst MAX_SCHEMA_BYTES = 512 * 1024;\nconst MAX_ARGUMENT_BYTES = 2 * 1024 * 1024;\nconst MAX_RESULT_BYTES = 5 * 1024 * 1024;\nconst MAX_JSON_DEPTH = 64;\nconst MAX_JSON_NODES = 50_000;\nconst MAX_DESCRIPTION_LENGTH = 20_000;\n// `@` and `#` are part of the persisted custom-integration identity grammar:\n// `custom:<manifest>@<sha>#<connection>`. They are safe in JSON store keys and\n// are sanitized before an id contributes to a runtime tool name.\nconst SERVER_ID = /^[A-Za-z0-9][A-Za-z0-9._:@#-]{0,127}$/;\nconst TOOL_NAME = /^[A-Za-z0-9_.:-]{1,128}$/;\nconst ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nconst UNSAFE_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\n\nexport function validateServerId(id: unknown, label = 'server id'): string {\n if (typeof id !== 'string' || !SERVER_ID.test(id) || UNSAFE_KEYS.has(id)) {\n throw new Error(`${label} must match ${SERVER_ID.source}`);\n }\n return id;\n}\n\nexport function validateServerCount(count: number): void {\n if (count > MAX_SERVERS) {\n throw new Error(`MCP store exceeds the ${MAX_SERVERS.toString()} server limit`);\n }\n}\n\nexport function validateServerConfig(value: unknown, label = 'server config'): McpServerConfig {\n const config = requireRecord(value, label);\n const hasCommand = Object.hasOwn(config, 'command');\n const hasUrl = Object.hasOwn(config, 'url');\n if (hasCommand === hasUrl) {\n throw new Error(`${label} must contain exactly one of command or url`);\n }\n return hasCommand ? validateStdioConfig(config, label) : validateRemoteConfig(config, label);\n}\n\nexport function normalizeChildCatalog(\n server: string,\n advertised: unknown,\n): McpToolDescriptor[] {\n validateServerId(server);\n if (!Array.isArray(advertised)) throw new Error(`server \"${server}\" returned a non-array tool catalog`);\n if (advertised.length > MAX_TOOLS_PER_SERVER) {\n throw new Error(\n `server \"${server}\" advertised ${advertised.length.toString()} tools; limit is ${MAX_TOOLS_PER_SERVER.toString()}`,\n );\n }\n\n const originals = new Set<string>();\n return advertised.map((raw, index) => {\n const tool = requireRecord(raw, `server \"${server}\" tool ${index.toString()}`);\n const name = tool.name;\n if (typeof name !== 'string' || !TOOL_NAME.test(name)) {\n throw new Error(`server \"${server}\" advertised an invalid tool name at index ${index.toString()}`);\n }\n if (originals.has(name)) throw new Error(`server \"${server}\" advertised duplicate tool \"${name}\"`);\n originals.add(name);\n const description = tool.description === undefined ? '' : requireBoundedString(\n tool.description,\n `server \"${server}\" tool \"${name}\" description`,\n MAX_DESCRIPTION_LENGTH,\n );\n const parameters = cloneBoundedJson(\n tool.inputSchema,\n `server \"${server}\" tool \"${name}\" input schema`,\n MAX_SCHEMA_BYTES,\n );\n if (!isRecord(parameters)) {\n throw new Error(`server \"${server}\" tool \"${name}\" input schema must be an object`);\n }\n return {\n prefixed: buildNamespacedToolName(server, name),\n server,\n original: name,\n label: (description || name).slice(0, 80),\n description,\n parameters,\n };\n });\n}\n\nexport function validateToolArguments(args: unknown): Record<string, unknown> | undefined {\n if (args === undefined) return undefined;\n const cloned = cloneBoundedJson(args, 'MCP tool arguments', MAX_ARGUMENT_BYTES);\n if (!isRecord(cloned)) throw new Error('MCP tool arguments must be an object');\n return cloned;\n}\n\nexport function normalizeToolResult(result: unknown): McpToolCallResult {\n const cloned = cloneBoundedJson(result, 'MCP tool result', MAX_RESULT_BYTES);\n if (!isRecord(cloned) || !Array.isArray(cloned.content)) {\n throw new Error('MCP tool result must be an object with a content array');\n }\n for (const [index, item] of cloned.content.entries()) {\n if (!isRecord(item)) throw new Error(`MCP tool result content[${index.toString()}] must be an object`);\n }\n if (cloned.isError !== undefined && typeof cloned.isError !== 'boolean') {\n throw new Error('MCP tool result isError must be a boolean when present');\n }\n if (cloned.structuredContent !== undefined && !isRecord(cloned.structuredContent)) {\n throw new Error('MCP tool result structuredContent must be an object when present');\n }\n return cloned as McpToolCallResult;\n}\n\nexport function redactErrorResult(\n result: McpToolCallResult,\n config: McpServerConfig,\n): McpToolCallResult {\n if (!result.isError) return result;\n return {\n ...result,\n content: result.content.map((item) => (\n item.type === 'text' && typeof item.text === 'string'\n ? { ...item, text: redactSensitiveText(item.text, config) }\n : item\n )),\n };\n}\n\nexport function cloneToolDescriptor(tool: McpToolDescriptor): McpToolDescriptor {\n return {\n ...tool,\n parameters: cloneBoundedJson(tool.parameters, `tool \"${tool.prefixed}\" schema`, MAX_SCHEMA_BYTES),\n };\n}\n\nexport function redactSensitiveText(text: unknown, config?: McpServerConfig): string {\n let output = String(text)\n .slice(0, MAX_DESCRIPTION_LENGTH)\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+/gi, '$1 [REDACTED]')\n .replace(/\\b(api[_-]?key|access[_-]?token|refresh[_-]?token|secret|password)\\s*[=:]\\s*[^\\s,;]+/gi, '$1=[REDACTED]')\n .replace(/\\balfe_[A-Za-z0-9_-]{8,}/g, '[REDACTED]');\n for (const secret of configSecrets(config)) {\n if (secret.length < 4) continue;\n output = output.split(secret).join('[REDACTED]');\n }\n return output;\n}\n\nfunction validateStdioConfig(config: Record<string, unknown>, label: string): StdioServerConfig {\n const command = requireBoundedString(config.command, `${label}.command`, 4096);\n rejectControlCharacters(command, `${label}.command`);\n const result: StdioServerConfig = { command };\n if (config.args !== undefined) {\n if (!Array.isArray(config.args) || config.args.length > 256) {\n throw new Error(`${label}.args must be an array with at most 256 entries`);\n }\n result.args = config.args.map((arg, index) => {\n const checked = requireBoundedString(arg, `${label}.args[${index.toString()}]`, 32 * 1024);\n rejectNul(checked, `${label}.args[${index.toString()}]`);\n return checked;\n });\n }\n if (config.env !== undefined) result.env = validateStringMap(config.env, `${label}.env`, ENV_NAME, 256, 64 * 1024);\n if (config.cwd !== undefined) {\n const cwd = requireBoundedString(config.cwd, `${label}.cwd`, 4096);\n rejectNul(cwd, `${label}.cwd`);\n if (!isAbsolute(cwd)) throw new Error(`${label}.cwd must be an absolute path`);\n result.cwd = cwd;\n }\n if (config.connectionTimeoutMs !== undefined) {\n result.connectionTimeoutMs = validateTimeout(config.connectionTimeoutMs, `${label}.connectionTimeoutMs`);\n }\n return result;\n}\n\nfunction validateRemoteConfig(config: Record<string, unknown>, label: string): RemoteServerConfig {\n const rawUrl = requireBoundedString(config.url, `${label}.url`, 4096);\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n throw new Error(`${label}.url must be an absolute URL`);\n }\n if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error(`${label}.url must use http or https`);\n if (parsed.protocol === 'http:' && !isLoopbackHost(parsed.hostname)) {\n throw new Error(`${label}.url must use https unless it targets loopback`);\n }\n if (parsed.username || parsed.password) throw new Error(`${label}.url must not contain credentials`);\n if (parsed.hash) throw new Error(`${label}.url must not contain a fragment`);\n const result: RemoteServerConfig = { url: parsed.toString() };\n if (config.transport !== undefined) {\n if (config.transport !== 'sse' && config.transport !== 'streamable-http') {\n throw new Error(`${label}.transport must be sse or streamable-http`);\n }\n result.transport = config.transport;\n }\n if (config.headers !== undefined) {\n result.headers = validateStringMap(config.headers, `${label}.headers`, HEADER_NAME, 64, 32 * 1024, true);\n }\n if (config.connectionTimeoutMs !== undefined) {\n result.connectionTimeoutMs = validateTimeout(config.connectionTimeoutMs, `${label}.connectionTimeoutMs`);\n }\n return result;\n}\n\nfunction validateStringMap(\n value: unknown,\n label: string,\n keyPattern: RegExp,\n maxEntries: number,\n maxValueLength: number,\n rejectControls = false,\n): Record<string, string> {\n const record = requireRecord(value, label);\n const entries = Object.entries(record);\n if (entries.length > maxEntries) throw new Error(`${label} has too many entries`);\n const result: Record<string, string> = {};\n for (const [key, raw] of entries) {\n if (!keyPattern.test(key) || UNSAFE_KEYS.has(key)) throw new Error(`${label} contains invalid key \"${key}\"`);\n const checked = requireBoundedString(raw, `${label}.${key}`, maxValueLength);\n rejectNul(checked, `${label}.${key}`);\n if (rejectControls) rejectControlCharacters(checked, `${label}.${key}`);\n result[key] = checked;\n }\n return result;\n}\n\nfunction validateTimeout(value: unknown, label: string): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0 || value > 300_000) {\n throw new Error(`${label} must be an integer from 0 to 300000`);\n }\n return value;\n}\n\nfunction cloneBoundedJson<T>(value: T, label: string, maxBytes: number): T {\n let nodes = 0;\n const seen = new WeakSet();\n const visit = (item: unknown, depth: number): void => {\n nodes += 1;\n if (nodes > MAX_JSON_NODES) throw new Error(`${label} exceeds the JSON node limit`);\n if (depth > MAX_JSON_DEPTH) throw new Error(`${label} exceeds the JSON depth limit`);\n if (item === null || typeof item === 'boolean' || typeof item === 'number') {\n if (typeof item === 'number' && !Number.isFinite(item)) throw new Error(`${label} contains a non-finite number`);\n return;\n }\n if (typeof item === 'string') {\n if (Buffer.byteLength(item, 'utf8') > maxBytes) throw new Error(`${label} contains an oversized string`);\n return;\n }\n if (typeof item !== 'object') throw new Error(`${label} contains a non-JSON value`);\n if (seen.has(item)) throw new Error(`${label} contains a cycle`);\n seen.add(item);\n if (!Array.isArray(item) && Object.getPrototypeOf(item) !== Object.prototype && Object.getPrototypeOf(item) !== null) {\n throw new Error(`${label} contains a non-plain object`);\n }\n for (const [key, child] of Object.entries(item)) {\n if (UNSAFE_KEYS.has(key)) throw new Error(`${label} contains unsafe key \"${key}\"`);\n visit(child, depth + 1);\n }\n };\n visit(value, 0);\n const serialized = JSON.stringify(value);\n if (Buffer.byteLength(serialized, 'utf8') > maxBytes) throw new Error(`${label} exceeds the byte limit`);\n const parsed: unknown = JSON.parse(serialized);\n return parsed as T;\n}\n\nfunction requireRecord(value: unknown, label: string): Record<string, unknown> {\n if (!isRecord(value)) throw new Error(`${label} must be an object`);\n for (const key of Object.keys(value)) {\n if (UNSAFE_KEYS.has(key)) throw new Error(`${label} contains unsafe key \"${key}\"`);\n }\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction requireBoundedString(value: unknown, label: string, maxLength: number): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > maxLength) {\n throw new Error(`${label} must be a non-empty string of at most ${maxLength.toString()} characters`);\n }\n return value;\n}\n\nfunction rejectNul(value: string, label: string): void {\n if (value.includes('\\0')) throw new Error(`${label} must not contain NUL`);\n}\n\nfunction rejectControlCharacters(value: string, label: string): void {\n for (const char of value) {\n const code = char.charCodeAt(0);\n if (code <= 31 || code === 127) throw new Error(`${label} must not contain control characters`);\n }\n}\n\nfunction configSecrets(config: McpServerConfig | undefined): string[] {\n if (!config) return [];\n return 'command' in config\n ? Object.values(config.env ?? {})\n : [...Object.values(config.headers ?? {}), new URL(config.url).password].filter(Boolean);\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '[::1]' || /^127(?:\\.[0-9]{1,3}){3}$/.test(hostname);\n}\n","import type { Logger, McpServerConfig, McpToolDescriptor, McpToolCallResult, StdioServerConfig } from './types.js';\nimport {\n cloneToolDescriptor,\n normalizeChildCatalog,\n normalizeToolResult,\n redactSensitiveText,\n validateServerConfig,\n validateServerId,\n validateToolArguments,\n} from './validation.js';\n\nconst MAX_STDERR_LINE_LENGTH = 16 * 1024;\n\n/** Env keys OpenClaw rejects from stdio MCP env blocks. Filter them out before spawning. */\nexport const STDIO_ENV_DENYLIST = new Set([\n 'NODE_OPTIONS',\n 'PYTHONSTARTUP',\n 'PYTHONPATH',\n 'PERL5OPT',\n 'RUBYOPT',\n 'SHELLOPTS',\n 'PS4',\n]);\n\nexport function sanitizeStdioEnv(env: Record<string, string> | undefined): Record<string, string> {\n if (!env) return {};\n const safe: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n if (STDIO_ENV_DENYLIST.has(k)) continue;\n safe[k] = v;\n }\n return safe;\n}\n\n/** Per-connect context the Connection threads into the connect factory. */\nexport interface ConnectContext {\n /** Server name (store key) — for logging/attribution. */\n serverName: string;\n /**\n * When set, stdio children are spawned with `stderr: 'pipe'` and each stderr\n * line is delivered here. When absent, stderr stays `inherit` (host fd).\n */\n onStderrLine?: (line: string) => void;\n}\n\nexport interface ConnectionDeps {\n /**\n * Factory for an MCP Client connected to the given config. Injected so tests\n * can mock without spawning real processes. In production this wraps\n * `@modelcontextprotocol/sdk/client`. The context arg is optional so\n * existing test mocks keep working.\n */\n connect: (server: McpServerConfig, ctx?: ConnectContext) => Promise<McpClientHandle>;\n}\n\n/**\n * Minimal interface our connection layer needs from an MCP client. Mirrors\n * the @modelcontextprotocol/sdk Client surface but kept narrow so we can\n * mock cleanly in tests.\n */\nexport interface McpClientHandle {\n listTools(): Promise<{ name: string; description?: string; inputSchema: Record<string, unknown> }[]>;\n callTool(name: string, args: unknown, opts?: { signal?: AbortSignal }): Promise<McpToolCallResult>;\n close(): Promise<void>;\n /**\n * Register a callback fired when the underlying transport closes or errors\n * unexpectedly (e.g. the child process crashed). Lets the Connection drop\n * its dead client so the next call re-spawns. Optional so test mocks can\n * omit it.\n */\n onClose?(handler: () => void): void;\n}\n\n/**\n * One Connection per MCP server. Owns lifecycle (lazy-spawn, close, refresh-lock).\n * Refresh-lock pattern adapted from AIWerk `index.ts:219-250` — prevents\n * reconnect + `notifications/tools/list_changed` race.\n */\nexport class Connection {\n readonly name: string;\n readonly config: McpServerConfig;\n private readonly deps: ConnectionDeps;\n private readonly logger: Logger | undefined;\n\n private client: McpClientHandle | undefined;\n private tools: McpToolDescriptor[] = [];\n private connectInFlight: Promise<void> | undefined;\n private refreshInFlight = false;\n private refreshQueued = false;\n private lastUsedAt = Date.now();\n\n /** Set while `close()` runs so the transport's onclose isn't treated as a crash. */\n private closing = false;\n /** Consecutive failed connect attempts — drives reconnect backoff. */\n private consecutiveFailures = 0;\n /** Message from the most recent failed connect attempt; cleared on success. */\n private lastError: string | undefined;\n /** Epoch ms before which re-connect attempts fast-fail (crash-loop guard). */\n private reconnectBlockedUntilMs = 0;\n\n private static readonly RECONNECT_BACKOFF_BASE_MS = 500;\n private static readonly RECONNECT_BACKOFF_MAX_MS = 30_000;\n\n private readonly onUnexpectedClose: (() => void) | undefined;\n private readonly onStderrLine: ((line: string) => void) | undefined;\n private readonly connectTimeoutMs: number;\n /** Whether any connect has ever been attempted — drives the eager retry sweep. */\n private connectAttempted = false;\n\n constructor(params: {\n name: string;\n config: McpServerConfig;\n deps: ConnectionDeps;\n logger?: Logger;\n /** Fired when the transport closes unexpectedly (crash), after internal cleanup. */\n onUnexpectedClose?: () => void;\n /** Threaded to the connect factory — pipes stdio child stderr when set. */\n onStderrLine?: (line: string) => void;\n /** Bound (ms) on one connect + discovery attempt. 0/undefined disables. */\n connectTimeoutMs?: number;\n }) {\n this.name = validateServerId(params.name);\n this.config = validateServerConfig(params.config);\n this.deps = params.deps;\n this.logger = params.logger;\n this.onUnexpectedClose = params.onUnexpectedClose;\n this.onStderrLine = params.onStderrLine;\n this.connectTimeoutMs = params.connectTimeoutMs ?? 0;\n }\n\n /** Returns the most recent known tool list. May be empty if the server hasn't connected yet. */\n snapshotTools(): McpToolDescriptor[] {\n return this.tools.map(cloneToolDescriptor);\n }\n\n /** Whether an MCP child process / remote connection has been established. */\n isConnected(): boolean {\n return this.client !== undefined;\n }\n\n /** Tools currently advertised; 0 until the server connects + discovers. */\n toolCount(): number {\n return this.tools.length;\n }\n\n /** Consecutive failed connect attempts; 0 when healthy. */\n failureCount(): number {\n return this.consecutiveFailures;\n }\n\n /** Message from the most recent failed connect attempt, if any. */\n lastErrorMessage(): string | undefined {\n return this.lastError;\n }\n\n /**\n * Whether a connect was ever attempted (success or failure). A reconciled\n * connection that was never warmed has neither a client nor a `lastError` —\n * this flag lets an eager host's retry sweep find it without also\n * resurrecting cleanly-closed (idle-reaped) connections.\n */\n hasConnectAttempted(): boolean {\n return this.connectAttempted;\n }\n\n /** Idle timestamp for reaping. */\n idleSinceMs(): number {\n return Date.now() - this.lastUsedAt;\n }\n\n /**\n * Lazy connect + tool discovery. Safe to call concurrently; in-flight\n * connects coalesce.\n */\n async ensureConnected(): Promise<void> {\n if (this.client) return;\n if (this.connectInFlight) return this.connectInFlight;\n if (Date.now() < this.reconnectBlockedUntilMs) {\n throw new Error(\n `server \"${this.name}\" is in reconnect backoff after ${this.consecutiveFailures.toString()} failed attempt(s)`,\n );\n }\n this.connectInFlight = this.connectAndDiscover().finally(() => {\n this.connectInFlight = undefined;\n });\n return this.connectInFlight;\n }\n\n private async connectAndDiscover(): Promise<void> {\n this.connectAttempted = true;\n const safeConfig = 'command' in this.config\n ? ({ ...this.config, env: sanitizeStdioEnv(this.config.env) } satisfies StdioServerConfig)\n : this.config;\n this.logger?.debug(`[mcp-bundler] connecting server \"${this.name}\"`);\n // The whole connect + discovery runs inside `attempt` so the outer await\n // can race it against `connectTimeoutMs`. Covering connect() itself is\n // load-bearing: a spawn/URL/auth failure throws there (before listTools),\n // and that is the COMMON failure mode for a freshly-added server —\n // without it such failures never recorded `lastError`, never incremented\n // `consecutiveFailures`, and never armed the reconnect backoff. The\n // attempt closes its own client when discovery fails after the spawn, so\n // the child is never orphaned even when the timeout has already moved on.\n const attempt = (async () => {\n const c = await this.deps.connect(safeConfig, {\n serverName: this.name,\n onStderrLine: this.onStderrLine,\n });\n try {\n const advertised = await c.listTools();\n return { client: c, advertised };\n } catch (err) {\n await c.close().catch(() => undefined);\n throw err;\n }\n })();\n try {\n const { client, advertised } = await this.raceConnectTimeout(attempt);\n this.client = client;\n this.closing = false;\n // Drop the dead client on an unexpected transport close so the next\n // call re-spawns instead of calling into a corpse. Bind the callback to\n // THIS handle so a late close from an already-replaced client can't wipe\n // out a freshly respawned one.\n client.onClose?.(() => { this.handleUnexpectedClose(client); });\n this.tools = normalizeChildCatalog(this.name, advertised);\n this.lastUsedAt = Date.now();\n this.consecutiveFailures = 0;\n this.lastError = undefined;\n this.reconnectBlockedUntilMs = 0;\n this.logger?.info(`[mcp-bundler] server \"${this.name}\" connected, ${this.tools.length.toString()} tool(s)`);\n } catch (err) {\n // If the timeout won the race, the attempt may still land later —\n // close that late client so the child isn't orphaned or adopted.\n void attempt.then(({ client }) => client.close()).catch(() => undefined);\n this.consecutiveFailures += 1;\n this.lastError = redactSensitiveText(err instanceof Error ? err.message : String(err), this.config);\n const backoff = Math.min(\n Connection.RECONNECT_BACKOFF_BASE_MS * 2 ** (this.consecutiveFailures - 1),\n Connection.RECONNECT_BACKOFF_MAX_MS,\n );\n this.reconnectBlockedUntilMs = Date.now() + backoff;\n throw err;\n }\n }\n\n /** Race the attempt against `connectTimeoutMs`; 0 disables the bound. */\n private async raceConnectTimeout<T>(attempt: Promise<T>): Promise<T> {\n const ms = this.connectTimeoutMs;\n if (ms <= 0) return attempt;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(\n `server \"${this.name}\" connect timed out after ${ms.toString()}ms — spawned but did not complete the MCP handshake/discovery`,\n ));\n }, ms);\n if (typeof timer === 'object' && 'unref' in timer) {\n (timer as { unref: () => void }).unref();\n }\n });\n try {\n return await Promise.race([attempt, timeout]);\n } finally {\n clearTimeout(timer);\n }\n }\n\n /**\n * Handle an unexpected transport close (crash / network drop). Clears the\n * dead client + tools so the next `ensureConnected` re-spawns. No-op if we\n * initiated the close ourselves (idle reap / reconcile removal).\n */\n private handleUnexpectedClose(handle: McpClientHandle): void {\n // Ignore if we initiated the close, or if this callback belongs to a\n // client we've already replaced (stale late-fire after a respawn).\n if (this.closing || this.client !== handle) return;\n this.logger?.warn(`[mcp-bundler] server \"${this.name}\" connection closed unexpectedly; will re-spawn on next use`);\n this.client = undefined;\n this.tools = [];\n // `onClose` can also represent a transport error callback. Close this\n // exact handle best-effort so a replacement never runs alongside it.\n void handle.close().catch(() => undefined);\n try {\n this.onUnexpectedClose?.();\n } catch {\n /* host hook must never break the connection lifecycle */\n }\n }\n\n /**\n * Re-discover tools. Used on reconnect or `tools/list_changed` notification.\n * Refresh-lock collapses concurrent refreshes; if one is in flight, the next\n * is queued (max 1 queued, since N>1 queued provides no extra freshness).\n */\n async refresh(): Promise<void> {\n if (!this.client) return this.ensureConnected();\n if (this.refreshInFlight) {\n this.refreshQueued = true;\n return;\n }\n this.refreshInFlight = true;\n try {\n const handle = this.client;\n const advertised = await handle.listTools();\n // A late refresh from a dead/replaced client must not overwrite the\n // freshly-connected handle's catalog.\n if (this.client !== handle) return;\n this.tools = normalizeChildCatalog(this.name, advertised);\n this.logger?.debug(`[mcp-bundler] server \"${this.name}\" refreshed, ${this.tools.length.toString()} tool(s)`);\n } finally {\n this.refreshInFlight = false;\n if (this.refreshQueued) {\n this.refreshQueued = false;\n // Trigger one more refresh; do not await so caller isn't blocked on cascading refreshes.\n void this.refresh().catch((err: unknown) => {\n this.logger?.warn(`[mcp-bundler] queued refresh for \"${this.name}\" failed`, { err: err instanceof Error ? err.message : String(err) });\n });\n }\n }\n }\n\n async callTool(originalName: string, args: unknown, signal?: AbortSignal): Promise<McpToolCallResult> {\n await this.ensureConnected();\n if (!this.client) throw new Error(`server \"${this.name}\" failed to connect`);\n this.lastUsedAt = Date.now();\n const checkedArgs = validateToolArguments(args);\n const result = await this.client.callTool(originalName, checkedArgs, signal ? { signal } : undefined);\n return normalizeToolResult(result);\n }\n\n /**\n * Close the underlying transport. Idempotent. If a connect is in flight\n * (warmup racing with reconcile-removal), wait for it to settle and then\n * close the client it produced — otherwise the child process is orphaned.\n */\n async close(): Promise<void> {\n if (this.connectInFlight) {\n await this.connectInFlight.catch(() => undefined);\n }\n // Mark this close as intentional so the transport's onclose callback\n // doesn't trip the unexpected-close re-spawn path.\n this.closing = true;\n const c = this.client;\n this.client = undefined;\n this.tools = [];\n if (c) await c.close().catch((err: unknown) => {\n this.logger?.warn(`[mcp-bundler] close error for \"${this.name}\"`, { err: err instanceof Error ? err.message : String(err) });\n });\n }\n\n /**\n * Stable hash of the config for diff detection in `reconcile`.\n * Two configs with the same hash are equivalent (no restart needed).\n */\n configFingerprint(): string {\n return JSON.stringify(this.config);\n }\n}\n\n/**\n * Build the production `connect` factory using the official MCP SDK.\n * Kept in a separate function so tests can substitute a mock without\n * pulling the SDK into the test bundle.\n */\nexport async function defaultConnect(server: McpServerConfig, ctx?: ConnectContext): Promise<McpClientHandle> {\n const { Client } = await import('@modelcontextprotocol/sdk/client/index.js');\n const client = new Client({ name: 'alfe-mcp-bundler', version: '0.0.0' }, {});\n\n if ('command' in server) {\n const stdio = server;\n const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js');\n const onStderrLine = ctx?.onStderrLine;\n const transport = new StdioClientTransport({\n command: stdio.command,\n args: stdio.args ?? [],\n env: { ...sanitizeStdioEnv(stdio.env) } as Record<string, string>,\n cwd: stdio.cwd,\n // Default is 'inherit' (child stderr lands on the HOST's fd 2, invisible\n // to any output monitoring). Pipe only when the host consumes it — an\n // unread pipe would back-pressure the child's stderr writes.\n ...(onStderrLine ? { stderr: 'pipe' as const } : {}),\n });\n if (onStderrLine) {\n // The SDK exposes the PassThrough immediately when stderr:'pipe', so\n // attaching before connect() captures early startup output too.\n let carry = '';\n const emitLine = (raw: string): void => {\n if (raw.trim() === '') return;\n const line = raw.length > MAX_STDERR_LINE_LENGTH\n ? `${raw.slice(0, MAX_STDERR_LINE_LENGTH)}…[truncated]`\n : raw;\n try {\n onStderrLine(line);\n } catch {\n /* host hook must never break the transport */\n }\n };\n transport.stderr?.on('data', (chunk: Buffer) => {\n const parts = (carry + chunk.toString()).split('\\n');\n carry = parts.pop() ?? '';\n for (const line of parts) emitLine(line);\n if (carry.length > MAX_STDERR_LINE_LENGTH) {\n emitLine(carry);\n carry = '';\n }\n });\n transport.stderr?.on('end', () => {\n emitLine(carry);\n carry = '';\n });\n }\n await client.connect(transport);\n } else {\n const remote = server;\n if (remote.transport === 'streamable-http') {\n const { StreamableHTTPClientTransport } = await import('@modelcontextprotocol/sdk/client/streamableHttp.js');\n const transport = new StreamableHTTPClientTransport(new URL(remote.url), {\n requestInit: { headers: remote.headers ?? {} },\n });\n await client.connect(transport);\n } else {\n // SSE is deprecated in newer MCP SDK in favor of streamable-http, but\n // some servers still only support SSE — keep transport for back-compat.\n /* eslint-disable @typescript-eslint/no-deprecated */\n const { SSEClientTransport } = await import('@modelcontextprotocol/sdk/client/sse.js');\n const transport = new SSEClientTransport(new URL(remote.url), {\n requestInit: { headers: remote.headers ?? {} },\n });\n /* eslint-enable @typescript-eslint/no-deprecated */\n await client.connect(transport);\n }\n }\n\n let closeHandler: (() => void) | undefined;\n let closed = false;\n const fireClose = () => {\n if (closed) return;\n closed = true;\n closeHandler?.();\n };\n // The high-level SDK Client proxies its transport's lifecycle callbacks.\n client.onclose = fireClose;\n // Transport errors are diagnostic events; only `onclose` proves the\n // handle is unusable. Treating every SDK error as a close could spawn a\n // replacement while the original transport was still live.\n client.onerror = () => undefined;\n\n return {\n async listTools() {\n const result = await client.listTools();\n return result.tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema as Record<string, unknown>,\n }));\n },\n async callTool(name, args, opts) {\n return (await client.callTool({ name, arguments: args as Record<string, unknown> | undefined }, undefined, opts)) as McpToolCallResult;\n },\n async close() {\n closed = true; // suppress the onClose callback for an intentional close\n await client.close();\n },\n onClose(handler: () => void) {\n closeHandler = handler;\n },\n };\n}\n","import { Connection, defaultConnect, type ConnectionDeps } from './connection.js';\nimport { disambiguateAgainst } from './tool-naming.js';\nimport {\n cloneToolDescriptor,\n redactErrorResult,\n redactSensitiveText,\n validateServerConfig,\n validateServerCount,\n validateServerId,\n} from './validation.js';\nimport type {\n BundlerOptions,\n Logger,\n McpServerConfig,\n McpServerStatus,\n McpToolCallResult,\n McpToolDescriptor,\n McpToolErrorInfo,\n ReconcileDiff,\n} from './types.js';\n\nconst DEFAULT_IDLE_TTL_MS = 10 * 60 * 1000;\nconst DEFAULT_IDLE_SWEEP_INTERVAL_MS = 60 * 1000;\nconst DEFAULT_RETRY_SWEEP_INTERVAL_MS = 60 * 1000;\n// Generous enough for a cold `npx -y <pkg>` npm download on first spawn;\n// see BundlerOptions.connectTimeoutMs for why a bound must exist at all.\nconst DEFAULT_CONNECT_TIMEOUT_MS = 120 * 1000;\n\n/** First text content of an error result, for host error reporting. */\nfunction extractErrorText(result: McpToolCallResult): string {\n for (const item of result.content) {\n if (item.type === 'text' && typeof item.text === 'string') return item.text.slice(0, 500);\n }\n return '(no error text)';\n}\n\n/**\n * Provider-agnostic MCP server bundler. Holds N MCP server connections,\n * exposes a unified namespaced tool catalog, and routes calls to the right\n * server.\n *\n * Designed to be embedded in any host (OpenClaw plugin, AI proxy, Lambda).\n * Public surface is intentionally synchronous where the host needs sync\n * (snapshot, listTools), async only where I/O is unavoidable.\n */\nexport class McpBundler {\n private readonly logger: Logger | undefined;\n private readonly connections = new Map<string, Connection>();\n private readonly idleTtlMs: number;\n private readonly idleSweepIntervalMs: number;\n private idleSweepTimer: ReturnType<typeof setInterval> | undefined;\n private readonly retrySweepIntervalMs: number;\n private retrySweepTimer: ReturnType<typeof setInterval> | undefined;\n private retrySweepInFlight = false;\n private readonly connectTimeoutMs: number;\n private readonly retryNeverConnected: boolean;\n private readonly deps: ConnectionDeps;\n private readonly onToolError: ((info: McpToolErrorInfo) => void) | undefined;\n private readonly onServerCrash: ((server: string) => void) | undefined;\n private readonly onServerStderr: ((server: string, line: string) => void) | undefined;\n private disposed = false;\n // Serialize reconcile() so concurrent callers (multiple plugin tool factory\n // ticks within the same ms) don't interleave and orphan Connections, leaking\n // child processes. Acquired via a chain-of-promises latch.\n private reconcileLatch: Promise<unknown> = Promise.resolve();\n\n constructor(opts: BundlerOptions = {}, deps?: ConnectionDeps) {\n this.logger = opts.logger;\n this.idleTtlMs = checkedDuration(opts.idleTtlMs ?? DEFAULT_IDLE_TTL_MS, 'idleTtlMs');\n this.idleSweepIntervalMs = checkedDuration(\n opts.idleSweepIntervalMs ?? DEFAULT_IDLE_SWEEP_INTERVAL_MS,\n 'idleSweepIntervalMs',\n );\n this.retrySweepIntervalMs = checkedDuration(\n opts.retrySweepIntervalMs ?? DEFAULT_RETRY_SWEEP_INTERVAL_MS,\n 'retrySweepIntervalMs',\n );\n this.connectTimeoutMs = checkedDuration(\n opts.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,\n 'connectTimeoutMs',\n 300_000,\n );\n this.retryNeverConnected = opts.retryNeverConnected ?? false;\n this.deps = deps ?? { connect: defaultConnect };\n this.onToolError = opts.onToolError;\n this.onServerCrash = opts.onServerCrash;\n this.onServerStderr = opts.onServerStderr;\n if (this.idleTtlMs > 0) this.startIdleSweep();\n if (this.retrySweepIntervalMs > 0) this.startRetrySweep();\n }\n\n /** Construct a Connection with the host hooks bound to its server name. */\n private buildConnection(name: string, config: McpServerConfig): Connection {\n const crash = this.onServerCrash;\n const stderr = this.onServerStderr;\n return new Connection({\n name,\n config,\n deps: this.deps,\n logger: this.logger,\n connectTimeoutMs: config.connectionTimeoutMs ?? this.connectTimeoutMs,\n ...(crash ? { onUnexpectedClose: () => { crash(name); } } : {}),\n ...(stderr ? {\n onStderrLine: (line: string) => { stderr(name, redactSensitiveText(line, config)); },\n } : {}),\n });\n }\n\n /** Fire the host's tool-error hook; exceptions must never affect the call path. */\n private reportToolError(info: McpToolErrorInfo): void {\n try {\n this.onToolError?.(info);\n } catch {\n /* host hook must never break tool routing */\n }\n }\n\n /**\n * Diff `desired` against current connections, spawn newcomers, dispose\n * removals, hot-restart on config change. Pull-based — call whenever the\n * host's config snapshot may have changed. Cheap if no diff.\n *\n * Lazy: newly-added servers are NOT eagerly connected; they connect on the\n * first `callTool()` (or first `listTools()` after `forceDiscover()`).\n * This avoids paying spawn cost for servers the agent never uses.\n */\n async reconcile(desired: Record<string, McpServerConfig>): Promise<ReconcileDiff> {\n if (this.disposed) throw new Error('McpBundler: disposed');\n // Serialize reconciles. Caller awaits its slot; in-flight reconciles run\n // in declaration order. Errors don't poison the latch — `.catch` swallows\n // for chaining, the actual error rejects the awaited slot.\n const slot = this.reconcileLatch.then(async () => this.doReconcile(desired));\n this.reconcileLatch = slot.catch(() => undefined);\n return slot;\n }\n\n private async doReconcile(desired: Record<string, McpServerConfig>): Promise<ReconcileDiff> {\n if (this.disposed) throw new Error('McpBundler: disposed');\n const desiredEntries = Object.entries(desired);\n validateServerCount(desiredEntries.length);\n const checkedDesired: Record<string, McpServerConfig> = {};\n for (const [name, config] of desiredEntries) {\n checkedDesired[validateServerId(name)] = validateServerConfig(config, `server \"${name}\" config`);\n }\n const desiredNames = new Set(Object.keys(checkedDesired));\n const currentNames = new Set(this.connections.keys());\n\n const added: string[] = [];\n const removed: string[] = [];\n const changed: string[] = [];\n const unchanged: string[] = [];\n\n // Removals: dispose connections no longer in desired set.\n for (const name of currentNames) {\n if (!desiredNames.has(name)) {\n const conn = this.connections.get(name);\n this.connections.delete(name);\n if (conn) await conn.close();\n removed.push(name);\n }\n }\n\n // Additions and changes.\n for (const [name, config] of Object.entries(checkedDesired)) {\n const existing = this.connections.get(name);\n if (!existing) {\n this.connections.set(name, this.buildConnection(name, config));\n added.push(name);\n continue;\n }\n const nextFingerprint = JSON.stringify(config);\n if (existing.configFingerprint() !== nextFingerprint) {\n // Config changed — close old, replace with fresh (lazy reconnect).\n await existing.close();\n this.connections.set(name, this.buildConnection(name, config));\n changed.push(name);\n } else {\n unchanged.push(name);\n }\n }\n\n if (added.length || removed.length || changed.length) {\n this.logger?.info('[mcp-bundler] reconciled', {\n added: added.length,\n removed: removed.length,\n changed: changed.length,\n unchanged: unchanged.length,\n });\n }\n return { added, removed, changed, unchanged };\n }\n\n /**\n * Synchronous snapshot of all currently-known tools across connected servers.\n * Servers that have not connected yet contribute nothing. Intended for use\n * inside OpenClaw's plugin tool factory which must be sync.\n *\n * Tool names are namespaced and disambiguated (suffix `-2`, `-3` on collision)\n * so cross-server name clashes never produce duplicate registrations.\n */\n listTools(): McpToolDescriptor[] {\n return this.resolvedCatalog().map(({ descriptor }) => cloneToolDescriptor(descriptor));\n }\n\n /**\n * Eagerly connect to every configured server and discover tools. Used by\n * hosts that want a hot list rather than the lazy default. Errors are\n * swallowed per-server (logged), so one bad server doesn't fail the batch.\n */\n async warmup(): Promise<void> {\n if (this.disposed) return;\n await Promise.allSettled(\n Array.from(this.connections.values()).map(async (conn) => {\n try {\n await conn.ensureConnected();\n } catch (err) {\n this.logger?.warn(`[mcp-bundler] warmup failed for \"${conn.name}\"`, {\n err: err instanceof Error ? err.message : String(err),\n });\n }\n }),\n );\n }\n\n /**\n * Re-attempt every server that is NOT connected but HAS a recorded connect\n * failure (`connected: false && lastError`). This is the self-heal path: a\n * server that failed its first warm — because its backing credential /\n * account / network wasn't resolvable yet — gets reconnected once that\n * dependency appears, WITHOUT needing an operator to restart the daemon.\n *\n * Convergence: this only calls `ensureConnected()`, which honours each\n * Connection's own exponential reconnect backoff (`reconnectBlockedUntilMs`,\n * 500ms → 30s cap). A server that keeps `exit(1)`-ing fast-fails while in\n * backoff, so repeated sweeps are cheap and never become a tight crash-loop\n * — the backoff widens with each failure. Servers that connect on their\n * first warm are left alone, as are cleanly-closed (idle-reaped) ones.\n *\n * Lazily-added servers that were NEVER attempted (no client, no\n * `lastError`) are also left alone by default — but with\n * `retryNeverConnected` (the daemon's eager mode) the sweep picks them up,\n * so a server added after the host's warmup pass self-heals within one\n * sweep instead of stranding its tools until a restart.\n *\n * Returns the statuses of the servers it attempted (empty if none needed a\n * retry). Never throws — per-server failures are reflected in the status.\n */\n async retryFailed(): Promise<McpServerStatus[]> {\n if (this.disposed) return [];\n const targets = Array.from(this.connections.values()).filter(\n (conn) =>\n !conn.isConnected() &&\n (conn.lastErrorMessage() !== undefined ||\n (this.retryNeverConnected && !conn.hasConnectAttempted())),\n );\n if (targets.length === 0) return [];\n const results = await Promise.allSettled(\n targets.map(async (conn) => {\n try {\n await conn.ensureConnected();\n } catch {\n /* failure (or still-in-backoff) is recorded on the connection */\n }\n return this.statusOf(conn);\n }),\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? [r.value] : []));\n }\n\n /** Build the live status descriptor for one connection. */\n private statusOf(conn: Connection): McpServerStatus {\n const status: McpServerStatus = {\n name: conn.name,\n connected: conn.isConnected(),\n toolCount: conn.toolCount(),\n consecutiveFailures: conn.failureCount(),\n };\n const err = conn.lastErrorMessage();\n if (err !== undefined) status.lastError = err;\n return status;\n }\n\n /** Live status for every known server. Synchronous snapshot, no I/O. */\n statuses(): McpServerStatus[] {\n return Array.from(this.connections.values()).map((conn) => this.statusOf(conn));\n }\n\n /**\n * Eagerly connect ONE server and return its resulting status. Unlike\n * `warmup()` — which fans out over all servers and swallows failures with\n * no return value — this surfaces the outcome so a caller (e.g. the daemon\n * confirming an `alfe mcp add`) can report \"connected, N tools\" or the exact\n * connect error back to the agent.\n *\n * Never throws: a connect failure (or a warm timeout) is reflected in the\n * returned status (`connected: false`, `lastError` set). Returns `undefined`\n * only when the named server isn't present in the bundler.\n */\n async warmServer(name: string, timeoutMs?: number): Promise<McpServerStatus | undefined> {\n if (this.disposed) return undefined;\n const conn = this.connections.get(name);\n if (!conn) return undefined;\n const checkedTimeout = timeoutMs === undefined\n ? undefined\n : checkedDuration(timeoutMs, 'warmServer timeoutMs', 300_000);\n const connect = conn.ensureConnected();\n // If the timeout wins the race below, `connect` stays pending and could\n // reject later — swallow that so it never becomes an unhandled rejection.\n // The connection records its own `lastError`, which `statusOf` reads.\n void connect.catch(() => undefined);\n try {\n if (checkedTimeout !== undefined && checkedTimeout > 0) {\n await this.raceTimeout(connect, checkedTimeout, name);\n } else {\n await connect;\n }\n } catch (err) {\n const status = this.statusOf(conn);\n // A warm timeout is ours, not the connection's — make sure the status\n // carries a message even if the underlying connect hasn't failed yet.\n status.lastError ??= err instanceof Error ? err.message : String(err);\n return status;\n }\n return this.statusOf(conn);\n }\n\n /** Race a promise against a timeout, clearing the timer either way. */\n private async raceTimeout(p: Promise<void>, timeoutMs: number, name: string): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`server \"${name}\" warm timed out after ${timeoutMs.toString()}ms`));\n }, timeoutMs);\n if (typeof timer === 'object' && 'unref' in timer) {\n (timer as { unref: () => void }).unref();\n }\n });\n try {\n await Promise.race([p, timeout]);\n } finally {\n // The Promise executor runs synchronously, so `timer` is always set here.\n clearTimeout(timer);\n }\n }\n\n /**\n * Invoke a tool by its namespaced name. Routes to the originating server.\n * Errors are returned as `{ isError: true, content: [...] }` so a failing\n * tool doesn't crash the host.\n */\n async callTool(prefixed: string, args: unknown, signal?: AbortSignal): Promise<McpToolCallResult> {\n if (this.disposed) {\n return { isError: true, content: [{ type: 'text', text: 'mcp-bundler disposed' }] };\n }\n const route = this.routeToolName(prefixed);\n if (!route) {\n return {\n isError: true,\n content: [{ type: 'text', text: `unknown MCP tool: ${prefixed.slice(0, 128)}` }],\n };\n }\n try {\n const result = await route.connection.callTool(route.original, args, signal);\n if (result.isError) {\n this.reportToolError({\n server: route.connection.name,\n tool: route.original,\n prefixed,\n kind: 'result-error',\n message: redactSensitiveText(extractErrorText(result), route.connection.config),\n });\n }\n return redactErrorResult(result, route.connection.config);\n } catch (err) {\n const msg = redactSensitiveText(err instanceof Error ? err.message : String(err), route.connection.config);\n this.logger?.error(`[mcp-bundler] tool call failed for \"${prefixed}\"`, { err: msg });\n this.reportToolError({\n server: route.connection.name,\n tool: route.original,\n prefixed,\n kind: 'thrown',\n message: msg,\n });\n return {\n isError: true,\n content: [{ type: 'text', text: `tool ${prefixed} failed: ${msg}` }],\n };\n }\n }\n\n /**\n * Resolve a namespaced tool name back to its server connection and original\n * tool name. Returns undefined if the tool is not currently advertised.\n */\n private routeToolName(prefixed: string): { connection: Connection; original: string } | undefined {\n const match = this.resolvedCatalog().find(({ descriptor }) => descriptor.prefixed === prefixed);\n return match ? { connection: match.connection, original: match.descriptor.original } : undefined;\n }\n\n /**\n * Build one collision-resolved catalog used by BOTH registration and\n * routing. Keeping these views together prevents an advertised `-2` name\n * from becoming uncallable when two child names sanitize to the same key.\n */\n private resolvedCatalog(): { descriptor: McpToolDescriptor; connection: Connection }[] {\n const seen = new Set<string>();\n const resolved: { descriptor: McpToolDescriptor; connection: Connection }[] = [];\n for (const conn of this.connections.values()) {\n for (const tool of conn.snapshotTools()) {\n const finalName = disambiguateAgainst(tool.prefixed, seen);\n seen.add(finalName);\n resolved.push({\n connection: conn,\n descriptor: finalName === tool.prefixed ? tool : { ...tool, prefixed: finalName },\n });\n }\n }\n return resolved;\n }\n\n /**\n * Tear down all connections and stop background tasks. Idempotent.\n * Call from `registerRuntimeLifecycle({ cleanup })` in the host plugin.\n */\n async dispose(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n if (this.idleSweepTimer) {\n clearInterval(this.idleSweepTimer);\n this.idleSweepTimer = undefined;\n }\n if (this.retrySweepTimer) {\n clearInterval(this.retrySweepTimer);\n this.retrySweepTimer = undefined;\n }\n await Promise.allSettled(Array.from(this.connections.values()).map((c) => c.close()));\n this.connections.clear();\n }\n\n private startIdleSweep(): void {\n this.idleSweepTimer = setInterval(() => {\n void this.sweepIdle().catch((err: unknown) => {\n this.logger?.warn('[mcp-bundler] idle sweep error', {\n err: err instanceof Error ? err.message : String(err),\n });\n });\n }, this.idleSweepIntervalMs);\n // Don't keep the host process alive just for the sweep.\n if (typeof this.idleSweepTimer === 'object' && 'unref' in this.idleSweepTimer) {\n (this.idleSweepTimer as { unref: () => void }).unref();\n }\n }\n\n private startRetrySweep(): void {\n this.retrySweepTimer = setInterval(() => {\n // Guard against overlap: a slow retry (spawn/handshake) must not stack up\n // if the previous sweep is still resolving.\n if (this.retrySweepInFlight) return;\n this.retrySweepInFlight = true;\n void this.retryFailed()\n .then((attempted) => {\n if (attempted.length === 0) return;\n const healed = attempted.filter((s) => s.connected);\n const stillDown = attempted.filter((s) => !s.connected);\n this.logger?.debug('[mcp-bundler] retry sweep', {\n attempted: attempted.length,\n healed: healed.length,\n stillDown: stillDown.length,\n });\n for (const s of healed) {\n this.logger?.info(`[mcp-bundler] server \"${s.name}\" self-healed on retry sweep`, {\n toolCount: s.toolCount,\n });\n }\n })\n .catch((err: unknown) => {\n this.logger?.warn('[mcp-bundler] retry sweep error', {\n err: err instanceof Error ? err.message : String(err),\n });\n })\n .finally(() => {\n this.retrySweepInFlight = false;\n });\n }, this.retrySweepIntervalMs);\n // Don't keep the host process alive just for the sweep.\n if (typeof this.retrySweepTimer === 'object' && 'unref' in this.retrySweepTimer) {\n (this.retrySweepTimer as { unref: () => void }).unref();\n }\n }\n\n private async sweepIdle(): Promise<void> {\n if (this.idleTtlMs <= 0) return;\n const targets: Connection[] = [];\n for (const conn of this.connections.values()) {\n if (conn.isConnected() && conn.idleSinceMs() > this.idleTtlMs) {\n targets.push(conn);\n }\n }\n if (targets.length === 0) return;\n this.logger?.debug(`[mcp-bundler] reaping ${targets.length.toString()} idle server(s)`);\n await Promise.allSettled(targets.map((c) => c.close()));\n }\n}\n\nfunction checkedDuration(value: number, label: string, max = 86_400_000): number {\n if (!Number.isSafeInteger(value) || value < 0 || value > max) {\n throw new Error(`McpBundler ${label} must be an integer from 0 to ${max.toString()}`);\n }\n return value;\n}\n","import {\n closeSync,\n constants,\n fchmodSync,\n fstatSync,\n fsyncSync,\n lstatSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n watch,\n writeFileSync,\n type FSWatcher,\n} from 'node:fs';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { Logger, McpServerConfig, StdioServerConfig, RemoteServerConfig, McpTransportKind } from './types.js';\nimport { validateServerConfig, validateServerCount, validateServerId } from './validation.js';\n\n/**\n * Where a server entry came from. Used by `removeServersByOwner` so an\n * integration uninstall can drop only its own entries without touching\n * `cli`-owned (e.g. `alfe-platform`) or `manual`-owned (user-added) ones.\n */\nexport type ServerOwner = 'cli' | `integration:${string}` | 'manual';\n\ninterface StoredServerCommon {\n /** Where the entry came from — controls bulk-removal semantics. */\n owner: ServerOwner;\n /** ISO timestamp of first registration; preserved across updates. */\n addedAt: string;\n /** Optional semver of the providing package (e.g. `@alfe.ai/mcp-server` for `alfe-platform`). Used for drift detection on CLI upgrade. */\n version?: string;\n}\n\nexport type StoredServerEntry =\n | (StoredServerCommon & { transport: 'stdio' } & StdioServerConfig)\n | (StoredServerCommon & { transport: 'sse' | 'streamable-http' } & RemoteServerConfig);\n\nexport interface StoreSchema {\n servers: Record<string, StoredServerEntry>;\n config: {\n sessionIdleTtlMs?: number;\n };\n /**\n * Server names this manager has written into `openclaw.json#mcp.servers.*`.\n * Used to compute the mirror-write diff without re-reading openclaw.json\n * (which would be a second source of truth). Foreign keys not listed here\n * are preserved across mirror writes.\n */\n _ownedOpenclawKeys: string[];\n}\n\nconst DEFAULT_STORE_DIR = join(homedir(), '.alfe', 'mcp');\nconst DEFAULT_STORE_PATH = join(DEFAULT_STORE_DIR, 'servers.json');\n\n/** Inter-process lock tunings — exported as constants so tests can override. */\nconst LOCK_WAIT_MS = 5_000;\nconst LOCK_RETRY_INTERVAL_MS = 25;\nconst LOCK_STALE_MS = 10_000;\nconst MAX_STORE_BYTES = 1024 * 1024;\n\nexport interface StoreOptions {\n /** Absolute path to the store file. Defaults to `~/.alfe/mcp/servers.json`. */\n path?: string;\n logger?: Logger;\n}\n\n/**\n * On-disk source of truth for the bundler's configured servers.\n *\n * Mutations go through `update()` (read-modify-write with atomic\n * temp+rename) so a concurrent writer (e.g. two `alfe mcp add` invocations\n * racing) can't lose data — the second writer reads the first's state.\n *\n * Schema is owner-tagged so `removeServersByOwner` can implement\n * integration uninstall without touching CLI-owned or manual entries.\n */\nexport class Store {\n private readonly storePath: string;\n private readonly logger?: Logger;\n private watcher?: FSWatcher;\n private watcherListeners = new Set<() => void>();\n private rewatchTimer?: NodeJS.Timeout;\n\n constructor(opts: StoreOptions = {}) {\n this.storePath = opts.path ?? DEFAULT_STORE_PATH;\n if (!isAbsolute(this.storePath)) throw new Error('Store path must be absolute');\n this.logger = opts.logger;\n }\n\n get path(): string {\n return this.storePath;\n }\n\n read(): StoreSchema {\n let fd = -1;\n try {\n try {\n fd = openSync(this.storePath, constants.O_RDONLY | constants.O_NOFOLLOW);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return cloneEmpty();\n throw err;\n }\n const stat = fstatSync(fd);\n if (!stat.isFile()) throw new Error('store path is not a regular file');\n if (typeof process.getuid === 'function' && stat.uid !== process.getuid()) {\n throw new Error('store file is not owned by the current user');\n }\n if ((stat.mode & 0o077) !== 0) {\n // Safely migrate a legacy current-user store before reading secrets.\n fchmodSync(fd, 0o600);\n }\n if (stat.size > MAX_STORE_BYTES) {\n throw new Error(`store exceeds the ${MAX_STORE_BYTES.toString()} byte limit`);\n }\n const raw = readFileSync(fd, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n return normalize(parsed);\n } catch (err) {\n this.logger?.warn('[mcp-bundler/store] rejected unreadable or invalid store', {\n err: errMsg(err),\n path: this.storePath,\n });\n throw new Error(`Store.read: rejected ${this.storePath}: ${errMsg(err)}`, { cause: err });\n } finally {\n if (fd >= 0) closeSync(fd);\n }\n }\n\n /**\n * Read-modify-write with atomic temp+rename, guarded by an\n * inter-process lock file. Caller passes a pure function that\n * produces the next state; this serialises the mutation to disk in\n * one rename, which is atomic on POSIX and on Windows when the\n * target path is on the same volume.\n *\n * The lock guards the read-then-rename window so two processes\n * (e.g. two `alfe mcp add` shells, or the CLI racing the daemon)\n * can't drop each other's writes. The lock file is at\n * `<storePath>.lock`; locks whose recorded writer process is no longer\n * alive are reclaimed so a crashed writer doesn't wedge the store.\n *\n * Pure-function shape (instead of a `read()` then `write(next)`\n * pair) intentionally — it keeps the read-modify-write contract\n * local to each caller so two updates back-to-back never see each\n * other's partial state.\n */\n update(fn: (cur: StoreSchema) => StoreSchema): StoreSchema {\n mkdirSync(dirname(this.storePath), { recursive: true, mode: 0o700 });\n const release = this.acquireLock();\n try {\n const cur = this.read();\n const next = normalize(fn(cur));\n const payload = JSON.stringify(next, null, 2);\n if (Buffer.byteLength(payload, 'utf8') > MAX_STORE_BYTES) {\n throw new Error(`Store.update: result exceeds the ${MAX_STORE_BYTES.toString()} byte limit`);\n }\n const tempPath = `${this.storePath}.${String(process.pid)}.${randomUUID()}.tmp`;\n let tempFd = -1;\n try {\n tempFd = openSync(tempPath, 'wx', 0o600);\n writeFileSync(tempFd, payload, { encoding: 'utf8' });\n fsyncSync(tempFd);\n closeSync(tempFd);\n tempFd = -1;\n renameSync(tempPath, this.storePath);\n this.fsyncParentDirectory();\n } catch (err) {\n if (tempFd >= 0) closeSync(tempFd);\n try {\n unlinkSync(tempPath);\n } catch {\n // Best-effort cleanup; the random exclusive name cannot collide.\n }\n throw err;\n }\n return next;\n } finally {\n release();\n }\n }\n\n /**\n * Acquire an inter-process file lock by atomically creating a\n * sentinel via `openSync(lockPath, 'wx')`. Waits with bounded\n * backoff up to `LOCK_WAIT_MS`. A structured lock is reclaimed only when\n * its writer process is no longer alive; age alone cannot steal a lock\n * from a slow but valid writer. Old malformed/legacy locks retain a\n * conservative age fallback.\n *\n * Returns the release function. Single-process callers are\n * unaffected — re-entering the same process spins briefly while\n * the prior call's `finally` runs.\n */\n private acquireLock(): () => void {\n const lockPath = `${this.storePath}.lock`;\n const deadline = Date.now() + LOCK_WAIT_MS;\n let fd = -1;\n let heldDevice = -1;\n let heldInode = -1;\n for (;;) {\n try {\n fd = openSync(lockPath, 'wx', 0o600);\n const token = randomUUID();\n writeFileSync(fd, JSON.stringify({ pid: process.pid, token, createdAt: new Date().toISOString() }), 'utf8');\n fsyncSync(fd);\n const stat = fstatSync(fd);\n heldDevice = stat.dev;\n heldInode = stat.ino;\n break;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'EEXIST') throw err;\n const stale = this.inspectStaleLock(lockPath);\n if (stale) {\n try {\n const current = lstatSync(lockPath);\n if (current.dev === stale.device && current.ino === stale.inode) unlinkSync(lockPath);\n } catch {\n // Another process may have just released it — fall through and retry.\n }\n continue;\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `Store.update: timed out waiting for ${lockPath} (held by another writer or stale lock)`,\n );\n }\n sleepSync(LOCK_RETRY_INTERVAL_MS);\n }\n }\n const held = fd;\n return () => {\n try {\n closeSync(held);\n } catch {\n // ignore — the unlink is what releases the lock for the next writer.\n }\n try {\n const current = lstatSync(lockPath);\n if (current.dev === heldDevice && current.ino === heldInode) unlinkSync(lockPath);\n } catch {\n // ignore — already unlinked; inode identity prevents deleting a successor lock.\n }\n };\n }\n\n private inspectStaleLock(lockPath: string): { device: number; inode: number } | undefined {\n let fd = -1;\n let modifiedAt: number | undefined;\n let device: number | undefined;\n let inode: number | undefined;\n try {\n fd = openSync(lockPath, constants.O_RDONLY | constants.O_NOFOLLOW);\n const stat = fstatSync(fd);\n modifiedAt = stat.mtimeMs;\n device = stat.dev;\n inode = stat.ino;\n if (!stat.isFile() || stat.size > 4096) {\n return Date.now() - stat.mtimeMs > LOCK_STALE_MS ? { device, inode } : undefined;\n }\n const parsed: unknown = JSON.parse(readFileSync(fd, 'utf8'));\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return Date.now() - stat.mtimeMs > LOCK_STALE_MS ? { device, inode } : undefined;\n }\n const pid = (parsed as { pid?: unknown }).pid;\n if (!Number.isSafeInteger(pid) || (pid as number) <= 0) {\n return Date.now() - stat.mtimeMs > LOCK_STALE_MS ? { device, inode } : undefined;\n }\n return !processIsAlive(pid as number) ? { device, inode } : undefined;\n } catch {\n return modifiedAt !== undefined && device !== undefined && inode !== undefined &&\n Date.now() - modifiedAt > LOCK_STALE_MS\n ? { device, inode }\n : undefined;\n } finally {\n if (fd >= 0) closeSync(fd);\n }\n }\n\n private fsyncParentDirectory(): void {\n let fd = -1;\n try {\n fd = openSync(dirname(this.storePath), constants.O_RDONLY);\n fsyncSync(fd);\n } catch {\n // Some platforms/filesystems do not support fsync on directories.\n } finally {\n if (fd >= 0) closeSync(fd);\n }\n }\n\n /**\n * Watch the store file for external changes (e.g. another `alfe mcp add`\n * shelling out from a separate process). Returns an unsubscribe fn.\n *\n * Coalesces bursts via a 50 ms debounce — editors and atomic-rename\n * writers commonly fire multiple events per logical save.\n */\n watch(cb: () => void): () => void {\n this.watcherListeners.add(cb);\n this.ensureWatcher();\n return () => {\n this.watcherListeners.delete(cb);\n if (this.watcherListeners.size === 0) this.disposeWatcher();\n };\n }\n\n dispose(): void {\n this.watcherListeners.clear();\n this.disposeWatcher();\n }\n\n private ensureWatcher(): void {\n if (this.watcher) return;\n mkdirSync(dirname(this.storePath), { recursive: true, mode: 0o700 });\n // Some platforms / atomic renames make a per-file watch flaky after\n // a rename; watching the parent directory and filtering by basename\n // is more robust.\n const dir = dirname(this.storePath);\n const basename = this.storePath.slice(dir.length + 1);\n let pending: NodeJS.Timeout | undefined;\n const fire = (): void => {\n pending = undefined;\n for (const cb of this.watcherListeners) {\n try {\n cb();\n } catch (err) {\n this.logger?.warn('[mcp-bundler/store] watcher listener threw', { err: errMsg(err) });\n }\n }\n };\n try {\n this.watcher = watch(dir, (_event, fn) => {\n if (fn !== basename) return;\n if (pending) clearTimeout(pending);\n pending = setTimeout(fire, 50);\n });\n this.watcher.on('error', (err) => {\n this.logger?.warn('[mcp-bundler/store] watcher error; retrying in 1s', { err: errMsg(err) });\n this.disposeWatcher();\n if (!this.rewatchTimer && this.watcherListeners.size > 0) {\n this.rewatchTimer = setTimeout(() => {\n this.rewatchTimer = undefined;\n this.ensureWatcher();\n }, 1000);\n this.rewatchTimer.unref();\n }\n });\n } catch (err) {\n this.logger?.warn('[mcp-bundler/store] failed to start watcher', { err: errMsg(err) });\n }\n }\n\n private disposeWatcher(): void {\n if (this.watcher) {\n try {\n this.watcher.close();\n } catch {\n // close throws on already-disposed watchers; ignore.\n }\n this.watcher = undefined;\n }\n if (this.rewatchTimer) {\n clearTimeout(this.rewatchTimer);\n this.rewatchTimer = undefined;\n }\n }\n}\n\nexport function defaultStorePath(): string {\n return DEFAULT_STORE_PATH;\n}\n\n/**\n * One-way launch-identity fingerprint for cache invalidation across IPC.\n * Store entries contain credentials in env/headers, so consumers that only\n * need equality receive this digest rather than the executable configuration.\n */\nexport function serverLaunchFingerprint(entry: StoredServerEntry): string {\n const identity = {\n config: toServerConfig(entry),\n version: entry.version ?? null,\n };\n return `sha256:${createHash('sha256').update(stableJson(identity)).digest('hex')}`;\n}\n\n/** Pull the runtime config (transport + transport-specific fields) out of a stored entry. */\nexport function toServerConfig(entry: StoredServerEntry): McpServerConfig {\n if (entry.transport === 'stdio') {\n const { command, args, env, cwd, connectionTimeoutMs } = entry;\n const cfg: StdioServerConfig = { command };\n if (args) cfg.args = [...args];\n if (env) cfg.env = { ...env };\n if (cwd) cfg.cwd = cwd;\n if (connectionTimeoutMs !== undefined) cfg.connectionTimeoutMs = connectionTimeoutMs;\n return validateServerConfig(cfg);\n }\n const { url, transport, headers, connectionTimeoutMs } = entry;\n const cfg: RemoteServerConfig = { url, transport };\n if (headers) cfg.headers = { ...headers };\n if (connectionTimeoutMs !== undefined) cfg.connectionTimeoutMs = connectionTimeoutMs;\n return validateServerConfig(cfg);\n}\n\n/** Build a stored entry from a runtime config + ownership metadata. */\nexport function toStoredEntry(\n config: McpServerConfig,\n meta: { owner: ServerOwner; transport?: McpTransportKind; version?: string; addedAt?: string },\n): StoredServerEntry {\n validateOwner(meta.owner);\n const checked = validateServerConfig(config);\n const addedAt = meta.addedAt ?? new Date().toISOString();\n validateTimestamp(addedAt, 'addedAt');\n if (meta.version !== undefined) validateVersion(meta.version);\n if ('command' in checked) {\n return {\n transport: 'stdio',\n owner: meta.owner,\n addedAt,\n ...(meta.version !== undefined ? { version: meta.version } : {}),\n ...checked,\n };\n }\n const transport = meta.transport ?? checked.transport ?? 'sse';\n if (transport === 'stdio') {\n throw new Error('toStoredEntry: transport=stdio specified but config is remote-shaped');\n }\n return {\n owner: meta.owner,\n addedAt,\n ...(meta.version !== undefined ? { version: meta.version } : {}),\n ...checked,\n transport,\n };\n}\n\nfunction cloneEmpty(): StoreSchema {\n return { servers: {}, config: {}, _ownedOpenclawKeys: [] };\n}\n\nfunction normalize(raw: unknown): StoreSchema {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('store root must be an object');\n const r = raw as Record<string, unknown>;\n const rawServers = r.servers;\n if (!rawServers || typeof rawServers !== 'object' || Array.isArray(rawServers)) {\n throw new Error('store.servers must be an object');\n }\n const serverEntries = Object.entries(rawServers);\n validateServerCount(serverEntries.length);\n const servers: Record<string, StoredServerEntry> = {};\n for (const [id, rawEntry] of serverEntries) {\n validateServerId(id);\n if (!rawEntry || typeof rawEntry !== 'object' || Array.isArray(rawEntry)) {\n throw new Error(`store server \"${id}\" must be an object`);\n }\n const entry = rawEntry as Partial<StoredServerEntry>;\n validateOwner(entry.owner);\n validateTimestamp(entry.addedAt, `store server \"${id}\" addedAt`);\n if (entry.version !== undefined) validateVersion(entry.version);\n if (!['stdio', 'sse', 'streamable-http'].includes(String(entry.transport))) {\n throw new Error(`store server \"${id}\" has an invalid transport`);\n }\n const runtime = entry.transport === 'stdio'\n ? validateServerConfig(entry, `store server \"${id}\"`)\n : validateServerConfig({ ...entry, transport: entry.transport }, `store server \"${id}\"`);\n servers[id] = toStoredEntry(runtime, {\n owner: entry.owner,\n transport: entry.transport,\n addedAt: entry.addedAt,\n version: entry.version,\n });\n }\n const rawConfig: unknown = r.config ?? {};\n if (!rawConfig || typeof rawConfig !== 'object' || Array.isArray(rawConfig)) {\n throw new Error('store.config must be an object');\n }\n const config: StoreSchema['config'] = {};\n const ttl = (rawConfig as Record<string, unknown>).sessionIdleTtlMs;\n if (ttl !== undefined) {\n if (typeof ttl !== 'number' || !Number.isSafeInteger(ttl) || ttl < 0 || ttl > 86_400_000) {\n throw new Error('store.config.sessionIdleTtlMs must be an integer from 0 to 86400000');\n }\n config.sessionIdleTtlMs = ttl;\n }\n const rawOwned = r._ownedOpenclawKeys;\n if (rawOwned !== undefined && !Array.isArray(rawOwned)) {\n throw new Error('store._ownedOpenclawKeys must be an array');\n }\n const ownedValues: unknown[] = rawOwned ?? [];\n const owned = [...new Set(\n ownedValues.map((value) => validateServerId(value, 'store._ownedOpenclawKeys entry')),\n )];\n validateServerCount(owned.length);\n return {\n servers,\n config,\n _ownedOpenclawKeys: owned,\n };\n}\n\nfunction validateOwner(owner: unknown): asserts owner is ServerOwner {\n if (owner === 'cli' || owner === 'manual') return;\n if (typeof owner === 'string' && owner.startsWith('integration:')) {\n validateServerId(owner.slice('integration:'.length), 'integration owner id');\n return;\n }\n throw new Error('server owner must be cli, manual, or integration:<id>');\n}\n\nfunction validateTimestamp(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || !Number.isFinite(Date.parse(value))) {\n throw new Error(`${label} must be an ISO timestamp`);\n }\n}\n\nfunction validateVersion(value: unknown): asserts value is string {\n if (typeof value !== 'string' || !/^[0-9A-Za-z][0-9A-Za-z.+-]{0,127}$/.test(value)) {\n throw new Error('server version is invalid');\n }\n}\n\nfunction processIsAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ESRCH';\n }\n}\n\nconst sleepBuffer = new Int32Array(new SharedArrayBuffer(4));\nfunction sleepSync(ms: number): void {\n Atomics.wait(sleepBuffer, 0, 0, ms);\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n return `{${Object.keys(record)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`)\n .join(',')}}`;\n }\n return value === undefined ? 'null' : JSON.stringify(value);\n}\n","import type { McpBundler } from './bundler.js';\nimport { Store, toServerConfig, toStoredEntry, type ServerOwner, type StoredServerEntry } from './store.js';\nimport type { Logger, McpServerConfig, McpServerStatus, McpTransportKind } from './types.js';\nimport { validateServerId } from './validation.js';\n\nexport interface ManagerOptions {\n /** Pre-constructed store. If omitted, one is built with default options. */\n store?: Store;\n logger?: Logger;\n}\n\nexport interface AddServerOptions {\n /** Required — flat-namespace key under the bundler store. */\n id: string;\n /** Marks ownership for bulk removal. Defaults to `manual`. */\n owner?: ServerOwner;\n /** Semver of the providing package; used for CLI version-drift detection. */\n version?: string;\n /** Explicit transport hint for remote configs. Defaults to inferring from `config`. */\n transport?: McpTransportKind;\n}\n\n/**\n * Bundler manager — owns the `~/.alfe/mcp/servers.json` store and surfaces a\n * small CRUD API the CLI and integration applier both call into.\n *\n * Single source of truth: every consumer (daemon-hosted bundler, CLI `alfe mcp\n * list`, integration uninstall) reads from this store. Openclaw.json is no\n * longer kept in sync — the daemon hosts the bundler children and the\n * openclaw plugin reaches them via IPC, so the openclaw.json mirror became\n * dead weight and an active source of duplicate spawning on claude-cli /\n * codex-cli backends.\n *\n * Call `loadIntoBundler(bundler)` once at daemon startup to wire the store\n * into a live `McpBundler` — subsequent store mutations (including those\n * landed by other processes via the file watcher) re-reconcile automatically.\n */\nexport class Manager {\n private readonly store: Store;\n private readonly ownsStore: boolean;\n private readonly logger?: Logger;\n private bundler?: McpBundler;\n private changeListeners = new Set<() => void>();\n private storeUnsubscribe?: () => void;\n\n constructor(opts: ManagerOptions = {}) {\n this.ownsStore = opts.store === undefined;\n this.store = opts.store ?? new Store({ logger: opts.logger });\n this.logger = opts.logger;\n }\n\n /** Direct accessor — handy for tests and the CLI's `alfe mcp list`. */\n getStore(): Store {\n return this.store;\n }\n\n /**\n * Register or overwrite a server entry. Mutation lands in the store\n * synchronously; if a bundler has been attached via `loadIntoBundler`,\n * it is re-reconciled BEFORE `onChange` listeners fire. A reconcile error is\n * logged and does not roll back the durable store mutation, but listeners do\n * not fire against stale live state. The ordering is load-bearing: the daemon's `onChange`\n * handler warms the bundler's current connections, so the just-added\n * server must already have its Connection object or it is never warmed.\n */\n async addServer(config: McpServerConfig, opts: AddServerOptions): Promise<void> {\n validateServerId(opts.id, 'Manager.addServer id');\n const owner = opts.owner ?? 'manual';\n this.store.update((cur) => {\n const previousAddedAt = lookupAddedAt(cur.servers, opts.id);\n const entry = toStoredEntry(config, {\n owner,\n transport: opts.transport,\n version: opts.version,\n addedAt: previousAddedAt,\n });\n return {\n ...cur,\n servers: { ...cur.servers, [opts.id]: entry },\n };\n });\n if (await this.reconcileBundlerLogged()) this.fireChange();\n }\n\n /**\n * Remove a single server entry. No-op if the id isn't in the store.\n * Refuses to remove an entry whose owner doesn't match `expectedOwner`\n * when supplied — the CLI uses this to guard `alfe mcp remove` from\n * accidentally clobbering integration- or cli-owned entries.\n */\n async removeServer(id: string, opts: { expectedOwner?: ServerOwner } = {}): Promise<boolean> {\n validateServerId(id, 'Manager.removeServer id');\n const outcome = { removed: false };\n this.store.update((cur) => {\n const existing = lookupEntry(cur.servers, id);\n if (!existing) return cur;\n if (opts.expectedOwner && existing.owner !== opts.expectedOwner) {\n throw new Error(\n `Manager.removeServer: server \"${id}\" is owned by \"${existing.owner}\", not \"${opts.expectedOwner}\"`,\n );\n }\n outcome.removed = true;\n return {\n ...cur,\n servers: Object.fromEntries(Object.entries(cur.servers).filter(([key]) => key !== id)),\n };\n });\n if (!outcome.removed) return false;\n if (await this.reconcileBundlerLogged()) this.fireChange();\n return true;\n }\n\n /** Drop every entry whose owner matches — used by integration uninstall. */\n async removeServersByOwner(owner: ServerOwner): Promise<string[]> {\n const removed: string[] = [];\n this.store.update((cur) => {\n const next: Record<string, StoredServerEntry> = {};\n for (const [id, entry] of Object.entries(cur.servers)) {\n if (entry.owner === owner) {\n removed.push(id);\n } else {\n next[id] = entry;\n }\n }\n if (removed.length === 0) return cur;\n return { ...cur, servers: next };\n });\n if (removed.length > 0) {\n if (await this.reconcileBundlerLogged()) this.fireChange();\n }\n return removed;\n }\n\n /** Read-only snapshot for `alfe mcp list` and similar UIs. */\n listServers(): { id: string; entry: StoredServerEntry }[] {\n const snap = this.store.read();\n return Object.entries(snap.servers).map(([id, entry]) => ({ id, entry }));\n }\n\n /**\n * Live connection status per server from the attached bundler. Empty when\n * no bundler is attached (e.g. a CLI-only manager). Lets callers show\n * whether each registered server actually connected and how many tools it\n * advertises, instead of only the stored config.\n */\n serverStatuses(): McpServerStatus[] {\n return this.bundler ? this.bundler.statuses() : [];\n }\n\n /**\n * Reconcile the bundler against the current store (so a just-added entry\n * has a connection object) then eagerly connect ONE server and return its\n * status. Used by the daemon to CONFIRM an `alfe mcp add` actually connected\n * before replying to the agent — turning the fire-and-forget warm into a\n * result the caller can report (\"connected, N tools\" or the real error).\n *\n * Returns `null` when no bundler is attached or the id isn't present; never\n * throws (a connect failure is carried in the returned status).\n */\n async warmServer(id: string, timeoutMs?: number): Promise<McpServerStatus | null> {\n if (!this.bundler) return null;\n try {\n validateServerId(id, 'Manager.warmServer id');\n await this.reconcileBundler();\n return (await this.bundler.warmServer(id, timeoutMs)) ?? null;\n } catch (err) {\n this.logger?.warn('[mcp-bundler/manager] warm reconcile failed', { err: errMsg(err) });\n return null;\n }\n }\n\n /**\n * Push the current store contents into a bundler instance (which owns\n * connections / tools). Wires up a store watcher so external mutations\n * (e.g. another shell running `alfe mcp add`) re-reconcile.\n */\n async loadIntoBundler(bundler: McpBundler): Promise<void> {\n this.bundler = bundler;\n await this.reconcileBundler();\n this.storeUnsubscribe ??= this.store.watch(() => {\n void this.reconcileBundler().catch((err: unknown) => {\n this.logger?.warn('[mcp-bundler/manager] watcher reconcile failed', { err: errMsg(err) });\n });\n });\n }\n\n /** Subscribe to store mutations. Returns an unsubscribe fn. */\n onChange(cb: () => void): () => void {\n this.changeListeners.add(cb);\n return () => {\n this.changeListeners.delete(cb);\n };\n }\n\n /**\n * Detach from the bundler and stop watching the store. Safe to call\n * multiple times. An injected Store remains owned by its caller; a Store\n * constructed by this manager is disposed here.\n */\n async dispose(): Promise<void> {\n if (this.storeUnsubscribe) {\n this.storeUnsubscribe();\n this.storeUnsubscribe = undefined;\n }\n if (this.ownsStore) this.store.dispose();\n this.changeListeners.clear();\n this.bundler = undefined;\n return Promise.resolve();\n }\n\n /**\n * Awaited by every mutator so `onChange` listeners observe a bundler\n * that already contains the mutation. Reconcile failures are logged and\n * return false so callers preserve the durable mutation without notifying\n * listeners against stale derived state.\n */\n private async reconcileBundlerLogged(): Promise<boolean> {\n if (!this.bundler) return true;\n try {\n await this.reconcileBundler();\n return true;\n } catch (err) {\n this.logger?.warn('[mcp-bundler/manager] bundler reconcile failed', { err: errMsg(err) });\n return false;\n }\n }\n\n private async reconcileBundler(): Promise<void> {\n if (!this.bundler) return;\n const snap = this.store.read();\n const servers: Record<string, McpServerConfig> = {};\n for (const [id, entry] of Object.entries(snap.servers)) {\n servers[id] = toServerConfig(entry);\n }\n await this.bundler.reconcile(servers);\n }\n\n private fireChange(): void {\n for (const cb of this.changeListeners) {\n try {\n cb();\n } catch (err) {\n this.logger?.warn('[mcp-bundler/manager] onChange listener threw', { err: errMsg(err) });\n }\n }\n }\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Indexed access on `Record<string, T>` returns `T` (not `T | undefined`)\n * unless `noUncheckedIndexedAccess` is set in tsconfig. These helpers\n * make the optional-ness explicit so the lint rules that hate\n * always-truthy conditionals stop firing on real lookups.\n */\nfunction lookupEntry(\n servers: Record<string, StoredServerEntry>,\n id: string,\n): StoredServerEntry | undefined {\n return Object.hasOwn(servers, id) ? servers[id] : undefined;\n}\n\nfunction lookupAddedAt(servers: Record<string, StoredServerEntry>, id: string): string | undefined {\n const entry = lookupEntry(servers, id);\n return entry ? entry.addedAt : undefined;\n}\n","/**\n * Pattern A validator — locks the \"explicit selector arg\" contract for\n * credential-touching tools across the openclaw-* plugin family.\n *\n * Background\n * ----------\n * Pattern A says every credential-touching tool on a multi-account-capable\n * provider MUST take a required selector arg in its JSON Schema so the LLM\n * picks the account deliberately. The reference implementation lives in\n * `@alfe.ai/openclaw-google` (`google_run_command` / `google_disconnect_\n * account` both require `email`). PR 7 of channels-and-credential-driven-\n * integrations sweeps the same shape across notion / xero / myob.\n *\n * Why a validator\n * ---------------\n * The contract is easy to break by accident — a new tool gets added, the\n * selector arg gets forgotten, the LLM silently dispatches to whichever\n * account was loaded first. There's no runtime safety net once the plugin\n * is published. This validator runs in plugin build steps (or CI) and\n * fails the build if a tool that declares itself credential-touching\n * doesn't carry the selector.\n *\n * Scope of this file\n * ------------------\n * Pure functions — no I/O. Plugin packages call into these helpers from\n * their own build scripts (e.g. `pnpm build` or a dedicated lint task) and\n * pass in their `ToolDef[]` or `McpToolDescriptor[]` collection. The\n * validator does NOT know how to read manifests or files — it only checks\n * the shape of the in-memory descriptor list. Wiring is up to each plugin.\n *\n * Consumers\n * ---------\n * - `@alfe.ai/myob-mcp` — direct MCP, explicit TypeBox schemas.\n * - `@alfe.ai/notion-mcp` — proxy MCP, injects selector at runtime.\n * - `@alfe.ai/xero-mcp` — proxy MCP, injects selector at runtime.\n * - `@alfe.ai/openclaw-google` — already compliant; can opt-in for regression.\n *\n * Future\n * ------\n * When PR 7-deferred lands (atlassian / github / microsoft openclaw\n * packages), they hook into the same validator. The atlassian / github\n * cases will likely run the validator over the proxied child server's\n * `listTools()` response after schema-injection, to confirm the injection\n * actually landed on every tool.\n */\n\nimport type { McpToolDescriptor } from './types.js';\n\n// ── Public types ────────────────────────────────────────────\n\n/**\n * A tool descriptor that the validator can inspect. Plugins can pass\n * either {@link McpToolDescriptor} (for proxy plugins surfacing child\n * tools) or a leaner local shape (for direct-MCP plugins). Both come\n * down to a tool name and a JSON Schema parameter object.\n */\nexport interface ValidatableTool {\n /** Tool name as the LLM sees it (post-namespacing). */\n name: string;\n /** JSON Schema for tool parameters (the `inputSchema`). */\n parameters: Record<string, unknown>;\n}\n\nexport interface PatternAOptions {\n /**\n * The required selector property name. Provider-specific (Google uses\n * `email`; Notion will use `workspaceId`; Xero will use `xeroTenantId`;\n * MYOB will use `myobBusinessId`). Plugins MAY support more than one\n * acceptable name — pass an array.\n */\n selector: string | readonly string[];\n /**\n * Tool names exempt from the selector requirement — typically the\n * `list_accounts` discovery tool and any pure-utility tools that don't\n * touch credentials. Match is exact (post-namespacing).\n */\n exempt?: readonly string[];\n}\n\nexport interface PatternAViolation {\n tool: string;\n reason:\n | 'missing-selector-property'\n | 'selector-not-required'\n | 'selector-property-not-string';\n detail: string;\n}\n\n// ── Core check ───────────────────────────────────────────────\n\n/**\n * Validate that every non-exempt tool's JSON Schema declares the selector\n * property AND lists it in `required`. Returns the full set of violations\n * so the caller can report them all in one pass — failing fast on the\n * first one tends to hide cascading bugs in real plugins.\n *\n * The check is intentionally schema-shape-only — it does NOT execute the\n * tool, call the LLM, or talk to the cloud. It's a fast structural pass\n * suitable for build-time use.\n */\nexport function checkPatternA(\n tools: readonly ValidatableTool[],\n options: PatternAOptions,\n): PatternAViolation[] {\n const selectorNames = typeof options.selector === \"string\"\n ? [options.selector]\n : options.selector;\n if (selectorNames.length === 0 || selectorNames.some((name) => typeof name !== 'string' || name.length === 0)) {\n throw new Error('Pattern A selector must contain at least one non-empty property name');\n }\n const exempt = new Set(options.exempt ?? []);\n const violations: PatternAViolation[] = [];\n\n for (const tool of tools) {\n if (exempt.has(tool.name)) continue;\n\n const schema = isRecord(tool.parameters) ? tool.parameters : {};\n const rawProperties = schema.properties;\n const properties = isRecord(rawProperties) ? rawProperties : {};\n const required = Array.isArray(schema.required)\n ? schema.required.filter((value): value is string => typeof value === 'string')\n : [];\n const present = selectorNames.filter((name) => Object.hasOwn(properties, name));\n\n if (present.length === 0) {\n violations.push({\n tool: tool.name,\n reason: 'missing-selector-property',\n detail: `expected one of [${selectorNames.join(', ')}] in inputSchema.properties`,\n });\n continue;\n }\n\n const requiredSelectors = present.filter((name) => required.includes(name));\n if (requiredSelectors.length === 0) {\n violations.push({\n tool: tool.name,\n reason: 'selector-not-required',\n detail: `selector [${present.join(', ')}] present in properties but missing from inputSchema.required`,\n });\n continue;\n }\n\n const validSelector = requiredSelectors.find((name) => {\n const property = properties[name];\n return isRecord(property) && property.type === 'string';\n });\n if (!validSelector) {\n const foundTypes = requiredSelectors.map((name) => {\n const property = properties[name];\n return `${name}=${JSON.stringify(isRecord(property) ? property.type : undefined)}`;\n });\n violations.push({\n tool: tool.name,\n reason: 'selector-property-not-string',\n detail: `at least one required selector must be JSON Schema type=string (found ${foundTypes.join(', ')})`,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * Thin wrapper that throws an Error listing every violation if any are\n * present. Convenient for build scripts that want a single guard call.\n */\nexport function assertPatternA(\n tools: readonly ValidatableTool[],\n options: PatternAOptions,\n): void {\n const violations = checkPatternA(tools, options);\n if (violations.length === 0) return;\n const lines = violations.map((violation) => ` - [${violation.reason}] ${violation.tool}: ${violation.detail}`);\n throw new Error(\n `Pattern A validation failed for ${String(violations.length)} tool(s):\\n${lines.join('\\n')}`,\n );\n}\n\n/**\n * Cast an {@link McpToolDescriptor} (proxy-plugin shape) to the leaner\n * {@link ValidatableTool} the validator accepts. Useful for proxy\n * plugins that already maintain a `cachedTools: McpToolDescriptor[]`\n * collection.\n */\nexport function fromMcpDescriptor(descriptor: McpToolDescriptor): ValidatableTool {\n return { name: descriptor.prefixed, parameters: descriptor.parameters };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["isRecord","errMsg"],"sources":["../src/tool-naming.ts","../src/validation.ts","../src/connection.ts","../src/bundler.ts","../src/store.ts","../src/manager.ts","../src/pattern-a-validator.ts"],"sourcesContent":["/**\n * Tool name sanitization and collision handling.\n *\n * OpenClaw constraint: tool names must match `[A-Za-z0-9_-]` and be ≤64 chars.\n * Pattern mirrored from `openclaw/src/agents/pi-bundle-mcp-names.ts`.\n *\n * Strategy: prefix every tool with its server name (`{server}__{tool}`),\n * sanitize disallowed chars to `_`, truncate, then suffix-disambiguate\n * (`-2`, `-3`, ...) on collision.\n */\n\nconst DISALLOWED = /[^A-Za-z0-9_-]/g;\nconst MAX_LEN = 64;\nconst SEPARATOR = '__';\n\nexport function sanitizeNameSegment(value: string): string {\n return value.replace(DISALLOWED, '_');\n}\n\nexport function buildNamespacedToolName(server: string, tool: string): string {\n const sanitizedServer = sanitizeNameSegment(server);\n const sanitizedTool = sanitizeNameSegment(tool);\n const serverBudget = MAX_LEN - SEPARATOR.length - 1;\n const boundedServer = sanitizedServer.slice(0, serverBudget);\n const base = `${boundedServer}${SEPARATOR}${sanitizedTool}`;\n if (base.length <= MAX_LEN) return base;\n // Truncate from the tool side first to keep the server prefix intact.\n const reservedForServer = boundedServer.length + SEPARATOR.length;\n const toolBudget = Math.max(1, MAX_LEN - reservedForServer);\n return `${boundedServer}${SEPARATOR}${sanitizedTool.slice(0, toolBudget)}`;\n}\n\n/**\n * Disambiguate a candidate name against an existing set by appending `-2`, `-3`, etc.\n * Mutates nothing; returns the chosen name. Caller is responsible for inserting it\n * into the set.\n */\nexport function disambiguateAgainst(candidate: string, taken: ReadonlySet<string>): string {\n if (!taken.has(candidate)) return candidate;\n // At most `taken.size` candidate names can be occupied, so this bound is\n // guaranteed to find a free suffix without returning a second collision.\n for (let i = 2; i <= taken.size + 2; i += 1) {\n const suffix = `-${i.toString()}`;\n const room = MAX_LEN - suffix.length;\n const trimmed = candidate.length > room ? candidate.slice(0, room) : candidate;\n const next = `${trimmed}${suffix}`;\n if (!taken.has(next)) return next;\n }\n throw new Error('unable to disambiguate MCP tool name');\n}\n","import { isAbsolute } from 'node:path';\nimport type {\n McpServerConfig,\n McpToolCallResult,\n McpToolDescriptor,\n RemoteServerConfig,\n StdioServerConfig,\n} from './types.js';\nimport { buildNamespacedToolName } from './tool-naming.js';\n\nconst MAX_SERVERS = 256;\nconst MAX_TOOLS_PER_SERVER = 512;\nconst MAX_SCHEMA_BYTES = 512 * 1024;\nconst MAX_ARGUMENT_BYTES = 2 * 1024 * 1024;\nconst MAX_RESULT_BYTES = 5 * 1024 * 1024;\nconst MAX_JSON_DEPTH = 64;\nconst MAX_JSON_NODES = 50_000;\nconst MAX_DESCRIPTION_LENGTH = 20_000;\n// `@` and `#` are part of the persisted custom-integration identity grammar:\n// `custom:<manifest>@<sha>#<connection>`. They are safe in JSON store keys and\n// are sanitized before an id contributes to a runtime tool name.\nconst SERVER_ID = /^[A-Za-z0-9][A-Za-z0-9._:@#-]{0,127}$/;\nconst TOOL_NAME = /^[A-Za-z0-9_.:-]{1,128}$/;\nconst ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nconst UNSAFE_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\n\nexport function validateServerId(id: unknown, label = 'server id'): string {\n if (typeof id !== 'string' || !SERVER_ID.test(id) || UNSAFE_KEYS.has(id)) {\n throw new Error(`${label} must match ${SERVER_ID.source}`);\n }\n return id;\n}\n\nexport function validateServerCount(count: number): void {\n if (count > MAX_SERVERS) {\n throw new Error(`MCP store exceeds the ${MAX_SERVERS.toString()} server limit`);\n }\n}\n\nexport function validateServerConfig(value: unknown, label = 'server config'): McpServerConfig {\n const config = requireRecord(value, label);\n const hasCommand = Object.hasOwn(config, 'command');\n const hasUrl = Object.hasOwn(config, 'url');\n if (hasCommand === hasUrl) {\n throw new Error(`${label} must contain exactly one of command or url`);\n }\n return hasCommand ? validateStdioConfig(config, label) : validateRemoteConfig(config, label);\n}\n\nexport function normalizeChildCatalog(\n server: string,\n advertised: unknown,\n): McpToolDescriptor[] {\n validateServerId(server);\n if (!Array.isArray(advertised)) throw new Error(`server \"${server}\" returned a non-array tool catalog`);\n if (advertised.length > MAX_TOOLS_PER_SERVER) {\n throw new Error(\n `server \"${server}\" advertised ${advertised.length.toString()} tools; limit is ${MAX_TOOLS_PER_SERVER.toString()}`,\n );\n }\n\n const originals = new Set<string>();\n return advertised.map((raw, index) => {\n const tool = requireRecord(raw, `server \"${server}\" tool ${index.toString()}`);\n const name = tool.name;\n if (typeof name !== 'string' || !TOOL_NAME.test(name)) {\n throw new Error(`server \"${server}\" advertised an invalid tool name at index ${index.toString()}`);\n }\n if (originals.has(name)) throw new Error(`server \"${server}\" advertised duplicate tool \"${name}\"`);\n originals.add(name);\n const description = tool.description === undefined ? '' : requireBoundedString(\n tool.description,\n `server \"${server}\" tool \"${name}\" description`,\n MAX_DESCRIPTION_LENGTH,\n );\n const parameters = cloneBoundedJson(\n tool.inputSchema,\n `server \"${server}\" tool \"${name}\" input schema`,\n MAX_SCHEMA_BYTES,\n );\n if (!isRecord(parameters)) {\n throw new Error(`server \"${server}\" tool \"${name}\" input schema must be an object`);\n }\n return {\n prefixed: buildNamespacedToolName(server, name),\n server,\n original: name,\n label: (description || name).slice(0, 80),\n description,\n parameters,\n };\n });\n}\n\nexport function validateToolArguments(args: unknown): Record<string, unknown> | undefined {\n if (args === undefined) return undefined;\n const cloned = cloneBoundedJson(args, 'MCP tool arguments', MAX_ARGUMENT_BYTES);\n if (!isRecord(cloned)) throw new Error('MCP tool arguments must be an object');\n return cloned;\n}\n\nexport function normalizeToolResult(result: unknown): McpToolCallResult {\n const cloned = cloneBoundedJson(result, 'MCP tool result', MAX_RESULT_BYTES);\n if (!isRecord(cloned) || !Array.isArray(cloned.content)) {\n throw new Error('MCP tool result must be an object with a content array');\n }\n for (const [index, item] of cloned.content.entries()) {\n if (!isRecord(item)) throw new Error(`MCP tool result content[${index.toString()}] must be an object`);\n }\n if (cloned.isError !== undefined && typeof cloned.isError !== 'boolean') {\n throw new Error('MCP tool result isError must be a boolean when present');\n }\n if (cloned.structuredContent !== undefined && !isRecord(cloned.structuredContent)) {\n throw new Error('MCP tool result structuredContent must be an object when present');\n }\n return cloned as McpToolCallResult;\n}\n\nexport function redactErrorResult(\n result: McpToolCallResult,\n config: McpServerConfig,\n): McpToolCallResult {\n if (!result.isError) return result;\n return {\n ...result,\n content: result.content.map((item) => (\n item.type === 'text' && typeof item.text === 'string'\n ? { ...item, text: redactSensitiveText(item.text, config) }\n : item\n )),\n };\n}\n\nexport function cloneToolDescriptor(tool: McpToolDescriptor): McpToolDescriptor {\n return {\n ...tool,\n parameters: cloneBoundedJson(tool.parameters, `tool \"${tool.prefixed}\" schema`, MAX_SCHEMA_BYTES),\n };\n}\n\nexport function redactSensitiveText(text: unknown, config?: McpServerConfig): string {\n let output = String(text)\n .slice(0, MAX_DESCRIPTION_LENGTH)\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+/gi, '$1 [REDACTED]')\n .replace(/\\b(api[_-]?key|access[_-]?token|refresh[_-]?token|secret|password)\\s*[=:]\\s*[^\\s,;]+/gi, '$1=[REDACTED]')\n .replace(/\\balfe_[A-Za-z0-9_-]{8,}/g, '[REDACTED]');\n for (const secret of configSecrets(config)) {\n if (secret.length < 4) continue;\n output = output.split(secret).join('[REDACTED]');\n }\n return output;\n}\n\nfunction validateStdioConfig(config: Record<string, unknown>, label: string): StdioServerConfig {\n const command = requireBoundedString(config.command, `${label}.command`, 4096);\n rejectControlCharacters(command, `${label}.command`);\n const result: StdioServerConfig = { command };\n if (config.args !== undefined) {\n if (!Array.isArray(config.args) || config.args.length > 256) {\n throw new Error(`${label}.args must be an array with at most 256 entries`);\n }\n result.args = config.args.map((arg, index) => {\n const checked = requireBoundedString(arg, `${label}.args[${index.toString()}]`, 32 * 1024);\n rejectNul(checked, `${label}.args[${index.toString()}]`);\n return checked;\n });\n }\n if (config.env !== undefined) result.env = validateStringMap(config.env, `${label}.env`, ENV_NAME, 256, 64 * 1024);\n if (config.cwd !== undefined) {\n const cwd = requireBoundedString(config.cwd, `${label}.cwd`, 4096);\n rejectNul(cwd, `${label}.cwd`);\n if (!isAbsolute(cwd)) throw new Error(`${label}.cwd must be an absolute path`);\n result.cwd = cwd;\n }\n if (config.connectionTimeoutMs !== undefined) {\n result.connectionTimeoutMs = validateTimeout(config.connectionTimeoutMs, `${label}.connectionTimeoutMs`);\n }\n return result;\n}\n\nfunction validateRemoteConfig(config: Record<string, unknown>, label: string): RemoteServerConfig {\n const rawUrl = requireBoundedString(config.url, `${label}.url`, 4096);\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n throw new Error(`${label}.url must be an absolute URL`);\n }\n if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error(`${label}.url must use http or https`);\n if (parsed.protocol === 'http:' && !isLoopbackHost(parsed.hostname)) {\n throw new Error(`${label}.url must use https unless it targets loopback`);\n }\n if (parsed.username || parsed.password) throw new Error(`${label}.url must not contain credentials`);\n if (parsed.hash) throw new Error(`${label}.url must not contain a fragment`);\n const result: RemoteServerConfig = { url: parsed.toString() };\n if (config.transport !== undefined) {\n if (config.transport !== 'sse' && config.transport !== 'streamable-http') {\n throw new Error(`${label}.transport must be sse or streamable-http`);\n }\n result.transport = config.transport;\n }\n if (config.headers !== undefined) {\n result.headers = validateStringMap(config.headers, `${label}.headers`, HEADER_NAME, 64, 32 * 1024, true);\n }\n if (config.connectionTimeoutMs !== undefined) {\n result.connectionTimeoutMs = validateTimeout(config.connectionTimeoutMs, `${label}.connectionTimeoutMs`);\n }\n return result;\n}\n\nfunction validateStringMap(\n value: unknown,\n label: string,\n keyPattern: RegExp,\n maxEntries: number,\n maxValueLength: number,\n rejectControls = false,\n): Record<string, string> {\n const record = requireRecord(value, label);\n const entries = Object.entries(record);\n if (entries.length > maxEntries) throw new Error(`${label} has too many entries`);\n const result: Record<string, string> = {};\n for (const [key, raw] of entries) {\n if (!keyPattern.test(key) || UNSAFE_KEYS.has(key)) throw new Error(`${label} contains invalid key \"${key}\"`);\n const checked = requireBoundedString(raw, `${label}.${key}`, maxValueLength);\n rejectNul(checked, `${label}.${key}`);\n if (rejectControls) rejectControlCharacters(checked, `${label}.${key}`);\n result[key] = checked;\n }\n return result;\n}\n\nfunction validateTimeout(value: unknown, label: string): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0 || value > 300_000) {\n throw new Error(`${label} must be an integer from 0 to 300000`);\n }\n return value;\n}\n\nfunction cloneBoundedJson<T>(value: T, label: string, maxBytes: number): T {\n let nodes = 0;\n const seen = new WeakSet();\n const visit = (item: unknown, depth: number): void => {\n nodes += 1;\n if (nodes > MAX_JSON_NODES) throw new Error(`${label} exceeds the JSON node limit`);\n if (depth > MAX_JSON_DEPTH) throw new Error(`${label} exceeds the JSON depth limit`);\n if (item === null || typeof item === 'boolean' || typeof item === 'number') {\n if (typeof item === 'number' && !Number.isFinite(item)) throw new Error(`${label} contains a non-finite number`);\n return;\n }\n if (typeof item === 'string') {\n if (Buffer.byteLength(item, 'utf8') > maxBytes) throw new Error(`${label} contains an oversized string`);\n return;\n }\n if (typeof item !== 'object') throw new Error(`${label} contains a non-JSON value`);\n if (seen.has(item)) throw new Error(`${label} contains a cycle`);\n seen.add(item);\n if (!Array.isArray(item) && Object.getPrototypeOf(item) !== Object.prototype && Object.getPrototypeOf(item) !== null) {\n throw new Error(`${label} contains a non-plain object`);\n }\n for (const [key, child] of Object.entries(item)) {\n if (UNSAFE_KEYS.has(key)) throw new Error(`${label} contains unsafe key \"${key}\"`);\n visit(child, depth + 1);\n }\n };\n visit(value, 0);\n const serialized = JSON.stringify(value);\n if (Buffer.byteLength(serialized, 'utf8') > maxBytes) throw new Error(`${label} exceeds the byte limit`);\n const parsed: unknown = JSON.parse(serialized);\n return parsed as T;\n}\n\nfunction requireRecord(value: unknown, label: string): Record<string, unknown> {\n if (!isRecord(value)) throw new Error(`${label} must be an object`);\n for (const key of Object.keys(value)) {\n if (UNSAFE_KEYS.has(key)) throw new Error(`${label} contains unsafe key \"${key}\"`);\n }\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction requireBoundedString(value: unknown, label: string, maxLength: number): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > maxLength) {\n throw new Error(`${label} must be a non-empty string of at most ${maxLength.toString()} characters`);\n }\n return value;\n}\n\nfunction rejectNul(value: string, label: string): void {\n if (value.includes('\\0')) throw new Error(`${label} must not contain NUL`);\n}\n\nfunction rejectControlCharacters(value: string, label: string): void {\n for (const char of value) {\n const code = char.charCodeAt(0);\n if (code <= 31 || code === 127) throw new Error(`${label} must not contain control characters`);\n }\n}\n\nfunction configSecrets(config: McpServerConfig | undefined): string[] {\n if (!config) return [];\n return 'command' in config\n ? Object.values(config.env ?? {})\n : [...Object.values(config.headers ?? {}), new URL(config.url).password].filter(Boolean);\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '[::1]' || /^127(?:\\.[0-9]{1,3}){3}$/.test(hostname);\n}\n","import type { Logger, McpServerConfig, McpToolDescriptor, McpToolCallResult, StdioServerConfig } from './types.js';\nimport {\n cloneToolDescriptor,\n normalizeChildCatalog,\n normalizeToolResult,\n redactSensitiveText,\n validateServerConfig,\n validateServerId,\n validateToolArguments,\n} from './validation.js';\n\nconst MAX_STDERR_LINE_LENGTH = 16 * 1024;\n\n/** Env keys OpenClaw rejects from stdio MCP env blocks. Filter them out before spawning. */\nexport const STDIO_ENV_DENYLIST = new Set([\n 'NODE_OPTIONS',\n 'PYTHONSTARTUP',\n 'PYTHONPATH',\n 'PERL5OPT',\n 'RUBYOPT',\n 'SHELLOPTS',\n 'PS4',\n]);\n\nexport function sanitizeStdioEnv(env: Record<string, string> | undefined): Record<string, string> {\n if (!env) return {};\n const safe: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n if (STDIO_ENV_DENYLIST.has(k)) continue;\n safe[k] = v;\n }\n return safe;\n}\n\n/** Per-connect context the Connection threads into the connect factory. */\nexport interface ConnectContext {\n /** Server name (store key) — for logging/attribution. */\n serverName: string;\n /**\n * When set, stdio children are spawned with `stderr: 'pipe'` and each stderr\n * line is delivered here. When absent, stderr stays `inherit` (host fd).\n */\n onStderrLine?: (line: string) => void;\n}\n\nexport interface ConnectionDeps {\n /**\n * Factory for an MCP Client connected to the given config. Injected so tests\n * can mock without spawning real processes. In production this wraps\n * `@modelcontextprotocol/sdk/client`. The context arg is optional so\n * existing test mocks keep working.\n */\n connect: (server: McpServerConfig, ctx?: ConnectContext) => Promise<McpClientHandle>;\n}\n\n/**\n * Minimal interface our connection layer needs from an MCP client. Mirrors\n * the @modelcontextprotocol/sdk Client surface but kept narrow so we can\n * mock cleanly in tests.\n */\nexport interface McpClientHandle {\n listTools(): Promise<{ name: string; description?: string; inputSchema: Record<string, unknown> }[]>;\n callTool(name: string, args: unknown, opts?: { signal?: AbortSignal }): Promise<McpToolCallResult>;\n close(): Promise<void>;\n /**\n * Register a callback fired when the underlying transport closes or errors\n * unexpectedly (e.g. the child process crashed). Lets the Connection drop\n * its dead client so the next call re-spawns. Optional so test mocks can\n * omit it.\n */\n onClose?(handler: () => void): void;\n}\n\n/**\n * One Connection per MCP server. Owns lifecycle (lazy-spawn, close, refresh-lock).\n * Refresh-lock pattern adapted from AIWerk `index.ts:219-250` — prevents\n * reconnect + `notifications/tools/list_changed` race.\n */\nexport class Connection {\n readonly name: string;\n readonly config: McpServerConfig;\n private readonly deps: ConnectionDeps;\n private readonly logger: Logger | undefined;\n\n private client: McpClientHandle | undefined;\n private tools: McpToolDescriptor[] = [];\n private connectInFlight: Promise<void> | undefined;\n private refreshInFlight = false;\n private refreshQueued = false;\n private lastUsedAt = Date.now();\n\n /** Set while `close()` runs so the transport's onclose isn't treated as a crash. */\n private closing = false;\n /** Consecutive failed connect attempts — drives reconnect backoff. */\n private consecutiveFailures = 0;\n /** Message from the most recent failed connect attempt; cleared on success. */\n private lastError: string | undefined;\n /** Epoch ms before which re-connect attempts fast-fail (crash-loop guard). */\n private reconnectBlockedUntilMs = 0;\n\n private static readonly RECONNECT_BACKOFF_BASE_MS = 500;\n private static readonly RECONNECT_BACKOFF_MAX_MS = 30_000;\n\n private readonly onUnexpectedClose: (() => void) | undefined;\n private readonly onStderrLine: ((line: string) => void) | undefined;\n private readonly connectTimeoutMs: number;\n /** Whether any connect has ever been attempted — drives the eager retry sweep. */\n private connectAttempted = false;\n\n constructor(params: {\n name: string;\n config: McpServerConfig;\n deps: ConnectionDeps;\n logger?: Logger;\n /** Fired when the transport closes unexpectedly (crash), after internal cleanup. */\n onUnexpectedClose?: () => void;\n /** Threaded to the connect factory — pipes stdio child stderr when set. */\n onStderrLine?: (line: string) => void;\n /** Bound (ms) on one connect + discovery attempt. 0/undefined disables. */\n connectTimeoutMs?: number;\n }) {\n this.name = validateServerId(params.name);\n this.config = validateServerConfig(params.config);\n this.deps = params.deps;\n this.logger = params.logger;\n this.onUnexpectedClose = params.onUnexpectedClose;\n this.onStderrLine = params.onStderrLine;\n this.connectTimeoutMs = params.connectTimeoutMs ?? 0;\n }\n\n /** Returns the most recent known tool list. May be empty if the server hasn't connected yet. */\n snapshotTools(): McpToolDescriptor[] {\n return this.tools.map(cloneToolDescriptor);\n }\n\n /** Whether an MCP child process / remote connection has been established. */\n isConnected(): boolean {\n return this.client !== undefined;\n }\n\n /** Tools currently advertised; 0 until the server connects + discovers. */\n toolCount(): number {\n return this.tools.length;\n }\n\n /** Consecutive failed connect attempts; 0 when healthy. */\n failureCount(): number {\n return this.consecutiveFailures;\n }\n\n /** Message from the most recent failed connect attempt, if any. */\n lastErrorMessage(): string | undefined {\n return this.lastError;\n }\n\n /**\n * Whether a connect was ever attempted (success or failure). A reconciled\n * connection that was never warmed has neither a client nor a `lastError` —\n * this flag lets an eager host's retry sweep find it without also\n * resurrecting cleanly-closed (idle-reaped) connections.\n */\n hasConnectAttempted(): boolean {\n return this.connectAttempted;\n }\n\n /** Idle timestamp for reaping. */\n idleSinceMs(): number {\n return Date.now() - this.lastUsedAt;\n }\n\n /**\n * Lazy connect + tool discovery. Safe to call concurrently; in-flight\n * connects coalesce.\n */\n async ensureConnected(): Promise<void> {\n if (this.client) return;\n if (this.connectInFlight) return this.connectInFlight;\n if (Date.now() < this.reconnectBlockedUntilMs) {\n throw new Error(\n `server \"${this.name}\" is in reconnect backoff after ${this.consecutiveFailures.toString()} failed attempt(s)`,\n );\n }\n this.connectInFlight = this.connectAndDiscover().finally(() => {\n this.connectInFlight = undefined;\n });\n return this.connectInFlight;\n }\n\n private async connectAndDiscover(): Promise<void> {\n this.connectAttempted = true;\n const safeConfig = 'command' in this.config\n ? ({ ...this.config, env: sanitizeStdioEnv(this.config.env) } satisfies StdioServerConfig)\n : this.config;\n this.logger?.debug(`[mcp-bundler] connecting server \"${this.name}\"`);\n // The whole connect + discovery runs inside `attempt` so the outer await\n // can race it against `connectTimeoutMs`. Covering connect() itself is\n // load-bearing: a spawn/URL/auth failure throws there (before listTools),\n // and that is the COMMON failure mode for a freshly-added server —\n // without it such failures never recorded `lastError`, never incremented\n // `consecutiveFailures`, and never armed the reconnect backoff. The\n // attempt closes its own client when discovery fails after the spawn, so\n // the child is never orphaned even when the timeout has already moved on.\n const attempt = (async () => {\n const c = await this.deps.connect(safeConfig, {\n serverName: this.name,\n onStderrLine: this.onStderrLine,\n });\n try {\n const advertised = await c.listTools();\n return { client: c, advertised };\n } catch (err) {\n await c.close().catch(() => undefined);\n throw err;\n }\n })();\n try {\n const { client, advertised } = await this.raceConnectTimeout(attempt);\n this.client = client;\n this.closing = false;\n // Drop the dead client on an unexpected transport close so the next\n // call re-spawns instead of calling into a corpse. Bind the callback to\n // THIS handle so a late close from an already-replaced client can't wipe\n // out a freshly respawned one.\n client.onClose?.(() => { this.handleUnexpectedClose(client); });\n this.tools = normalizeChildCatalog(this.name, advertised);\n this.lastUsedAt = Date.now();\n this.consecutiveFailures = 0;\n this.lastError = undefined;\n this.reconnectBlockedUntilMs = 0;\n this.logger?.info(`[mcp-bundler] server \"${this.name}\" connected, ${this.tools.length.toString()} tool(s)`);\n } catch (err) {\n // If the timeout won the race, the attempt may still land later —\n // close that late client so the child isn't orphaned or adopted.\n void attempt.then(({ client }) => client.close()).catch(() => undefined);\n this.consecutiveFailures += 1;\n this.lastError = redactSensitiveText(err instanceof Error ? err.message : String(err), this.config);\n const backoff = Math.min(\n Connection.RECONNECT_BACKOFF_BASE_MS * 2 ** (this.consecutiveFailures - 1),\n Connection.RECONNECT_BACKOFF_MAX_MS,\n );\n this.reconnectBlockedUntilMs = Date.now() + backoff;\n throw err;\n }\n }\n\n /** Race the attempt against `connectTimeoutMs`; 0 disables the bound. */\n private async raceConnectTimeout<T>(attempt: Promise<T>): Promise<T> {\n const ms = this.connectTimeoutMs;\n if (ms <= 0) return attempt;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(\n `server \"${this.name}\" connect timed out after ${ms.toString()}ms — spawned but did not complete the MCP handshake/discovery`,\n ));\n }, ms);\n if (typeof timer === 'object' && 'unref' in timer) {\n (timer as { unref: () => void }).unref();\n }\n });\n try {\n return await Promise.race([attempt, timeout]);\n } finally {\n clearTimeout(timer);\n }\n }\n\n /**\n * Handle an unexpected transport close (crash / network drop). Clears the\n * dead client + tools so the next `ensureConnected` re-spawns. No-op if we\n * initiated the close ourselves (idle reap / reconcile removal).\n */\n private handleUnexpectedClose(handle: McpClientHandle): void {\n // Ignore if we initiated the close, or if this callback belongs to a\n // client we've already replaced (stale late-fire after a respawn).\n if (this.closing || this.client !== handle) return;\n this.logger?.warn(`[mcp-bundler] server \"${this.name}\" connection closed unexpectedly; will re-spawn on next use`);\n this.client = undefined;\n this.tools = [];\n // `onClose` can also represent a transport error callback. Close this\n // exact handle best-effort so a replacement never runs alongside it.\n void handle.close().catch(() => undefined);\n try {\n this.onUnexpectedClose?.();\n } catch {\n /* host hook must never break the connection lifecycle */\n }\n }\n\n /**\n * Re-discover tools. Used on reconnect or `tools/list_changed` notification.\n * Refresh-lock collapses concurrent refreshes; if one is in flight, the next\n * is queued (max 1 queued, since N>1 queued provides no extra freshness).\n */\n async refresh(): Promise<void> {\n if (!this.client) return this.ensureConnected();\n if (this.refreshInFlight) {\n this.refreshQueued = true;\n return;\n }\n this.refreshInFlight = true;\n try {\n const handle = this.client;\n const advertised = await handle.listTools();\n // A late refresh from a dead/replaced client must not overwrite the\n // freshly-connected handle's catalog.\n if (this.client !== handle) return;\n this.tools = normalizeChildCatalog(this.name, advertised);\n this.logger?.debug(`[mcp-bundler] server \"${this.name}\" refreshed, ${this.tools.length.toString()} tool(s)`);\n } finally {\n this.refreshInFlight = false;\n if (this.refreshQueued) {\n this.refreshQueued = false;\n // Trigger one more refresh; do not await so caller isn't blocked on cascading refreshes.\n void this.refresh().catch((err: unknown) => {\n this.logger?.warn(`[mcp-bundler] queued refresh for \"${this.name}\" failed`, { err: err instanceof Error ? err.message : String(err) });\n });\n }\n }\n }\n\n async callTool(originalName: string, args: unknown, signal?: AbortSignal): Promise<McpToolCallResult> {\n await this.ensureConnected();\n if (!this.client) throw new Error(`server \"${this.name}\" failed to connect`);\n this.lastUsedAt = Date.now();\n const checkedArgs = validateToolArguments(args);\n const result = await this.client.callTool(originalName, checkedArgs, signal ? { signal } : undefined);\n return normalizeToolResult(result);\n }\n\n /**\n * Close the underlying transport. Idempotent. If a connect is in flight\n * (warmup racing with reconcile-removal), wait for it to settle and then\n * close the client it produced — otherwise the child process is orphaned.\n */\n async close(): Promise<void> {\n if (this.connectInFlight) {\n await this.connectInFlight.catch(() => undefined);\n }\n // Mark this close as intentional so the transport's onclose callback\n // doesn't trip the unexpected-close re-spawn path.\n this.closing = true;\n const c = this.client;\n this.client = undefined;\n this.tools = [];\n if (c) await c.close().catch((err: unknown) => {\n this.logger?.warn(`[mcp-bundler] close error for \"${this.name}\"`, { err: err instanceof Error ? err.message : String(err) });\n });\n }\n\n /**\n * Stable hash of the config for diff detection in `reconcile`.\n * Two configs with the same hash are equivalent (no restart needed).\n */\n configFingerprint(): string {\n return JSON.stringify(this.config);\n }\n}\n\n/**\n * Build the production `connect` factory using the official MCP SDK.\n * Kept in a separate function so tests can substitute a mock without\n * pulling the SDK into the test bundle.\n */\nexport async function defaultConnect(server: McpServerConfig, ctx?: ConnectContext): Promise<McpClientHandle> {\n const { Client } = await import('@modelcontextprotocol/sdk/client/index.js');\n const client = new Client({ name: 'alfe-mcp-bundler', version: '0.0.0' }, {});\n\n if ('command' in server) {\n const stdio = server;\n const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js');\n const onStderrLine = ctx?.onStderrLine;\n const transport = new StdioClientTransport({\n command: stdio.command,\n args: stdio.args ?? [],\n env: { ...sanitizeStdioEnv(stdio.env) } as Record<string, string>,\n cwd: stdio.cwd,\n // Default is 'inherit' (child stderr lands on the HOST's fd 2, invisible\n // to any output monitoring). Pipe only when the host consumes it — an\n // unread pipe would back-pressure the child's stderr writes.\n ...(onStderrLine ? { stderr: 'pipe' as const } : {}),\n });\n if (onStderrLine) {\n // The SDK exposes the PassThrough immediately when stderr:'pipe', so\n // attaching before connect() captures early startup output too.\n let carry = '';\n const emitLine = (raw: string): void => {\n if (raw.trim() === '') return;\n const line = raw.length > MAX_STDERR_LINE_LENGTH\n ? `${raw.slice(0, MAX_STDERR_LINE_LENGTH)}…[truncated]`\n : raw;\n try {\n onStderrLine(line);\n } catch {\n /* host hook must never break the transport */\n }\n };\n transport.stderr?.on('data', (chunk: Buffer) => {\n const parts = (carry + chunk.toString()).split('\\n');\n carry = parts.pop() ?? '';\n for (const line of parts) emitLine(line);\n if (carry.length > MAX_STDERR_LINE_LENGTH) {\n emitLine(carry);\n carry = '';\n }\n });\n transport.stderr?.on('end', () => {\n emitLine(carry);\n carry = '';\n });\n }\n await client.connect(transport);\n } else {\n const remote = server;\n if (remote.transport === 'streamable-http') {\n const { StreamableHTTPClientTransport } = await import('@modelcontextprotocol/sdk/client/streamableHttp.js');\n const transport = new StreamableHTTPClientTransport(new URL(remote.url), {\n requestInit: { headers: remote.headers ?? {} },\n });\n await client.connect(transport);\n } else {\n // SSE is deprecated in newer MCP SDK in favor of streamable-http, but\n // some servers still only support SSE — keep transport for back-compat.\n /* eslint-disable @typescript-eslint/no-deprecated */\n const { SSEClientTransport } = await import('@modelcontextprotocol/sdk/client/sse.js');\n const transport = new SSEClientTransport(new URL(remote.url), {\n requestInit: { headers: remote.headers ?? {} },\n });\n /* eslint-enable @typescript-eslint/no-deprecated */\n await client.connect(transport);\n }\n }\n\n let closeHandler: (() => void) | undefined;\n let closed = false;\n const fireClose = () => {\n if (closed) return;\n closed = true;\n closeHandler?.();\n };\n // The high-level SDK Client proxies its transport's lifecycle callbacks.\n client.onclose = fireClose;\n // Transport errors are diagnostic events; only `onclose` proves the\n // handle is unusable. Treating every SDK error as a close could spawn a\n // replacement while the original transport was still live.\n client.onerror = () => undefined;\n\n return {\n async listTools() {\n const result = await client.listTools();\n return result.tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema as Record<string, unknown>,\n }));\n },\n async callTool(name, args, opts) {\n return (await client.callTool({ name, arguments: args as Record<string, unknown> | undefined }, undefined, opts)) as McpToolCallResult;\n },\n async close() {\n closed = true; // suppress the onClose callback for an intentional close\n await client.close();\n },\n onClose(handler: () => void) {\n closeHandler = handler;\n },\n };\n}\n","import { Connection, defaultConnect, type ConnectionDeps } from './connection.js';\nimport { disambiguateAgainst } from './tool-naming.js';\nimport {\n cloneToolDescriptor,\n redactErrorResult,\n redactSensitiveText,\n validateServerConfig,\n validateServerCount,\n validateServerId,\n} from './validation.js';\nimport type {\n BundlerOptions,\n Logger,\n McpServerConfig,\n McpServerStatus,\n McpToolCallResult,\n McpToolDescriptor,\n McpToolErrorInfo,\n ReconcileDiff,\n} from './types.js';\n\nconst DEFAULT_IDLE_TTL_MS = 10 * 60 * 1000;\nconst DEFAULT_IDLE_SWEEP_INTERVAL_MS = 60 * 1000;\nconst DEFAULT_RETRY_SWEEP_INTERVAL_MS = 60 * 1000;\n// Generous enough for a cold `npx -y <pkg>` npm download on first spawn;\n// see BundlerOptions.connectTimeoutMs for why a bound must exist at all.\nconst DEFAULT_CONNECT_TIMEOUT_MS = 120 * 1000;\n\n/** First text content of an error result, for host error reporting. */\nfunction extractErrorText(result: McpToolCallResult): string {\n for (const item of result.content) {\n if (item.type === 'text' && typeof item.text === 'string') return item.text.slice(0, 500);\n }\n return '(no error text)';\n}\n\n/**\n * Provider-agnostic MCP server bundler. Holds N MCP server connections,\n * exposes a unified namespaced tool catalog, and routes calls to the right\n * server.\n *\n * Designed to be embedded in any host (OpenClaw plugin, AI proxy, Lambda).\n * Public surface is intentionally synchronous where the host needs sync\n * (snapshot, listTools), async only where I/O is unavoidable.\n */\nexport class McpBundler {\n private readonly logger: Logger | undefined;\n private readonly connections = new Map<string, Connection>();\n private readonly idleTtlMs: number;\n private readonly idleSweepIntervalMs: number;\n private idleSweepTimer: ReturnType<typeof setInterval> | undefined;\n private readonly retrySweepIntervalMs: number;\n private retrySweepTimer: ReturnType<typeof setInterval> | undefined;\n private retrySweepInFlight = false;\n private readonly connectTimeoutMs: number;\n private readonly retryNeverConnected: boolean;\n private readonly deps: ConnectionDeps;\n private readonly onToolError: ((info: McpToolErrorInfo) => void) | undefined;\n private readonly onServerCrash: ((server: string) => void) | undefined;\n private readonly onServerStderr: ((server: string, line: string) => void) | undefined;\n private disposed = false;\n // Serialize reconcile() so concurrent callers (multiple plugin tool factory\n // ticks within the same ms) don't interleave and orphan Connections, leaking\n // child processes. Acquired via a chain-of-promises latch.\n private reconcileLatch: Promise<unknown> = Promise.resolve();\n\n constructor(opts: BundlerOptions = {}, deps?: ConnectionDeps) {\n this.logger = opts.logger;\n this.idleTtlMs = checkedDuration(opts.idleTtlMs ?? DEFAULT_IDLE_TTL_MS, 'idleTtlMs');\n this.idleSweepIntervalMs = checkedDuration(\n opts.idleSweepIntervalMs ?? DEFAULT_IDLE_SWEEP_INTERVAL_MS,\n 'idleSweepIntervalMs',\n );\n this.retrySweepIntervalMs = checkedDuration(\n opts.retrySweepIntervalMs ?? DEFAULT_RETRY_SWEEP_INTERVAL_MS,\n 'retrySweepIntervalMs',\n );\n this.connectTimeoutMs = checkedDuration(\n opts.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,\n 'connectTimeoutMs',\n 300_000,\n );\n this.retryNeverConnected = opts.retryNeverConnected ?? false;\n this.deps = deps ?? { connect: defaultConnect };\n this.onToolError = opts.onToolError;\n this.onServerCrash = opts.onServerCrash;\n this.onServerStderr = opts.onServerStderr;\n if (this.idleTtlMs > 0) this.startIdleSweep();\n if (this.retrySweepIntervalMs > 0) this.startRetrySweep();\n }\n\n /** Construct a Connection with the host hooks bound to its server name. */\n private buildConnection(name: string, config: McpServerConfig): Connection {\n const crash = this.onServerCrash;\n const stderr = this.onServerStderr;\n return new Connection({\n name,\n config,\n deps: this.deps,\n logger: this.logger,\n connectTimeoutMs: config.connectionTimeoutMs ?? this.connectTimeoutMs,\n ...(crash ? { onUnexpectedClose: () => { crash(name); } } : {}),\n ...(stderr ? {\n onStderrLine: (line: string) => { stderr(name, redactSensitiveText(line, config)); },\n } : {}),\n });\n }\n\n /** Fire the host's tool-error hook; exceptions must never affect the call path. */\n private reportToolError(info: McpToolErrorInfo): void {\n try {\n this.onToolError?.(info);\n } catch {\n /* host hook must never break tool routing */\n }\n }\n\n /**\n * Diff `desired` against current connections, spawn newcomers, dispose\n * removals, hot-restart on config change. Pull-based — call whenever the\n * host's config snapshot may have changed. Cheap if no diff.\n *\n * Lazy: newly-added servers are NOT eagerly connected; they connect on the\n * first `callTool()` (or first `listTools()` after `forceDiscover()`).\n * This avoids paying spawn cost for servers the agent never uses.\n */\n async reconcile(desired: Record<string, McpServerConfig>): Promise<ReconcileDiff> {\n if (this.disposed) throw new Error('McpBundler: disposed');\n // Serialize reconciles. Caller awaits its slot; in-flight reconciles run\n // in declaration order. Errors don't poison the latch — `.catch` swallows\n // for chaining, the actual error rejects the awaited slot.\n const slot = this.reconcileLatch.then(async () => this.doReconcile(desired));\n this.reconcileLatch = slot.catch(() => undefined);\n return slot;\n }\n\n private async doReconcile(desired: Record<string, McpServerConfig>): Promise<ReconcileDiff> {\n if (this.disposed) throw new Error('McpBundler: disposed');\n const desiredEntries = Object.entries(desired);\n validateServerCount(desiredEntries.length);\n const checkedDesired: Record<string, McpServerConfig> = {};\n for (const [name, config] of desiredEntries) {\n checkedDesired[validateServerId(name)] = validateServerConfig(config, `server \"${name}\" config`);\n }\n const desiredNames = new Set(Object.keys(checkedDesired));\n const currentNames = new Set(this.connections.keys());\n\n const added: string[] = [];\n const removed: string[] = [];\n const changed: string[] = [];\n const unchanged: string[] = [];\n\n // Removals: dispose connections no longer in desired set.\n for (const name of currentNames) {\n if (!desiredNames.has(name)) {\n const conn = this.connections.get(name);\n this.connections.delete(name);\n if (conn) await conn.close();\n removed.push(name);\n }\n }\n\n // Additions and changes.\n for (const [name, config] of Object.entries(checkedDesired)) {\n const existing = this.connections.get(name);\n if (!existing) {\n this.connections.set(name, this.buildConnection(name, config));\n added.push(name);\n continue;\n }\n const nextFingerprint = JSON.stringify(config);\n if (existing.configFingerprint() !== nextFingerprint) {\n // Config changed — close old, replace with fresh (lazy reconnect).\n await existing.close();\n this.connections.set(name, this.buildConnection(name, config));\n changed.push(name);\n } else {\n unchanged.push(name);\n }\n }\n\n if (added.length || removed.length || changed.length) {\n this.logger?.info('[mcp-bundler] reconciled', {\n added: added.length,\n removed: removed.length,\n changed: changed.length,\n unchanged: unchanged.length,\n });\n }\n return { added, removed, changed, unchanged };\n }\n\n /**\n * Synchronous snapshot of all currently-known tools across connected servers.\n * Servers that have not connected yet contribute nothing. Intended for use\n * inside OpenClaw's plugin tool factory which must be sync.\n *\n * Tool names are namespaced and disambiguated (suffix `-2`, `-3` on collision)\n * so cross-server name clashes never produce duplicate registrations.\n */\n listTools(): McpToolDescriptor[] {\n return this.resolvedCatalog().map(({ descriptor }) => cloneToolDescriptor(descriptor));\n }\n\n /**\n * Eagerly connect to every configured server and discover tools. Used by\n * hosts that want a hot list rather than the lazy default. Errors are\n * swallowed per-server (logged), so one bad server doesn't fail the batch.\n */\n async warmup(): Promise<void> {\n if (this.disposed) return;\n await Promise.allSettled(\n Array.from(this.connections.values()).map(async (conn) => {\n try {\n await conn.ensureConnected();\n } catch (err) {\n this.logger?.warn(`[mcp-bundler] warmup failed for \"${conn.name}\"`, {\n err: err instanceof Error ? err.message : String(err),\n });\n }\n }),\n );\n }\n\n /**\n * Re-attempt every server that is NOT connected but HAS a recorded connect\n * failure (`connected: false && lastError`). This is the self-heal path: a\n * server that failed its first warm — because its backing credential /\n * account / network wasn't resolvable yet — gets reconnected once that\n * dependency appears, WITHOUT needing an operator to restart the daemon.\n *\n * Convergence: this only calls `ensureConnected()`, which honours each\n * Connection's own exponential reconnect backoff (`reconnectBlockedUntilMs`,\n * 500ms → 30s cap). A server that keeps `exit(1)`-ing fast-fails while in\n * backoff, so repeated sweeps are cheap and never become a tight crash-loop\n * — the backoff widens with each failure. Servers that connect on their\n * first warm are left alone, as are cleanly-closed (idle-reaped) ones.\n *\n * Lazily-added servers that were NEVER attempted (no client, no\n * `lastError`) are also left alone by default — but with\n * `retryNeverConnected` (the daemon's eager mode) the sweep picks them up,\n * so a server added after the host's warmup pass self-heals within one\n * sweep instead of stranding its tools until a restart.\n *\n * Returns the statuses of the servers it attempted (empty if none needed a\n * retry). Never throws — per-server failures are reflected in the status.\n */\n async retryFailed(): Promise<McpServerStatus[]> {\n if (this.disposed) return [];\n const targets = Array.from(this.connections.values()).filter(\n (conn) =>\n !conn.isConnected() &&\n (conn.lastErrorMessage() !== undefined ||\n (this.retryNeverConnected && !conn.hasConnectAttempted())),\n );\n if (targets.length === 0) return [];\n const results = await Promise.allSettled(\n targets.map(async (conn) => {\n try {\n await conn.ensureConnected();\n } catch {\n /* failure (or still-in-backoff) is recorded on the connection */\n }\n return this.statusOf(conn);\n }),\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? [r.value] : []));\n }\n\n /** Build the live status descriptor for one connection. */\n private statusOf(conn: Connection): McpServerStatus {\n const status: McpServerStatus = {\n name: conn.name,\n connected: conn.isConnected(),\n toolCount: conn.toolCount(),\n consecutiveFailures: conn.failureCount(),\n };\n const err = conn.lastErrorMessage();\n if (err !== undefined) status.lastError = err;\n return status;\n }\n\n /** Live status for every known server. Synchronous snapshot, no I/O. */\n statuses(): McpServerStatus[] {\n return Array.from(this.connections.values()).map((conn) => this.statusOf(conn));\n }\n\n /**\n * Eagerly connect ONE server and return its resulting status. Unlike\n * `warmup()` — which fans out over all servers and swallows failures with\n * no return value — this surfaces the outcome so a caller (e.g. the daemon\n * confirming an `alfe mcp add`) can report \"connected, N tools\" or the exact\n * connect error back to the agent.\n *\n * Never throws: a connect failure (or a warm timeout) is reflected in the\n * returned status (`connected: false`, `lastError` set). Returns `undefined`\n * only when the named server isn't present in the bundler.\n */\n async warmServer(name: string, timeoutMs?: number): Promise<McpServerStatus | undefined> {\n if (this.disposed) return undefined;\n const conn = this.connections.get(name);\n if (!conn) return undefined;\n const checkedTimeout = timeoutMs === undefined\n ? undefined\n : checkedDuration(timeoutMs, 'warmServer timeoutMs', 300_000);\n const connect = conn.ensureConnected();\n // If the timeout wins the race below, `connect` stays pending and could\n // reject later — swallow that so it never becomes an unhandled rejection.\n // The connection records its own `lastError`, which `statusOf` reads.\n void connect.catch(() => undefined);\n try {\n if (checkedTimeout !== undefined && checkedTimeout > 0) {\n await this.raceTimeout(connect, checkedTimeout, name);\n } else {\n await connect;\n }\n } catch (err) {\n const status = this.statusOf(conn);\n // A warm timeout is ours, not the connection's — make sure the status\n // carries a message even if the underlying connect hasn't failed yet.\n status.lastError ??= err instanceof Error ? err.message : String(err);\n return status;\n }\n return this.statusOf(conn);\n }\n\n /** Race a promise against a timeout, clearing the timer either way. */\n private async raceTimeout(p: Promise<void>, timeoutMs: number, name: string): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`server \"${name}\" warm timed out after ${timeoutMs.toString()}ms`));\n }, timeoutMs);\n if (typeof timer === 'object' && 'unref' in timer) {\n (timer as { unref: () => void }).unref();\n }\n });\n try {\n await Promise.race([p, timeout]);\n } finally {\n // The Promise executor runs synchronously, so `timer` is always set here.\n clearTimeout(timer);\n }\n }\n\n /**\n * Invoke a tool by its namespaced name. Routes to the originating server.\n * Errors are returned as `{ isError: true, content: [...] }` so a failing\n * tool doesn't crash the host.\n */\n async callTool(prefixed: string, args: unknown, signal?: AbortSignal): Promise<McpToolCallResult> {\n if (this.disposed) {\n return { isError: true, content: [{ type: 'text', text: 'mcp-bundler disposed' }] };\n }\n const route = this.routeToolName(prefixed);\n if (!route) {\n return {\n isError: true,\n content: [{ type: 'text', text: `unknown MCP tool: ${prefixed.slice(0, 128)}` }],\n };\n }\n try {\n const result = await route.connection.callTool(route.original, args, signal);\n if (result.isError) {\n this.reportToolError({\n server: route.connection.name,\n tool: route.original,\n prefixed,\n kind: 'result-error',\n message: redactSensitiveText(extractErrorText(result), route.connection.config),\n });\n }\n return redactErrorResult(result, route.connection.config);\n } catch (err) {\n const msg = redactSensitiveText(err instanceof Error ? err.message : String(err), route.connection.config);\n this.logger?.error(`[mcp-bundler] tool call failed for \"${prefixed}\"`, { err: msg });\n this.reportToolError({\n server: route.connection.name,\n tool: route.original,\n prefixed,\n kind: 'thrown',\n message: msg,\n });\n return {\n isError: true,\n content: [{ type: 'text', text: `tool ${prefixed} failed: ${msg}` }],\n };\n }\n }\n\n /**\n * Resolve a namespaced tool name back to its server connection and original\n * tool name. Returns undefined if the tool is not currently advertised.\n */\n private routeToolName(prefixed: string): { connection: Connection; original: string } | undefined {\n const match = this.resolvedCatalog().find(({ descriptor }) => descriptor.prefixed === prefixed);\n return match ? { connection: match.connection, original: match.descriptor.original } : undefined;\n }\n\n /**\n * Build one collision-resolved catalog used by BOTH registration and\n * routing. Keeping these views together prevents an advertised `-2` name\n * from becoming uncallable when two child names sanitize to the same key.\n */\n private resolvedCatalog(): { descriptor: McpToolDescriptor; connection: Connection }[] {\n const seen = new Set<string>();\n const resolved: { descriptor: McpToolDescriptor; connection: Connection }[] = [];\n for (const conn of this.connections.values()) {\n for (const tool of conn.snapshotTools()) {\n const finalName = disambiguateAgainst(tool.prefixed, seen);\n seen.add(finalName);\n resolved.push({\n connection: conn,\n descriptor: finalName === tool.prefixed ? tool : { ...tool, prefixed: finalName },\n });\n }\n }\n return resolved;\n }\n\n /**\n * Tear down all connections and stop background tasks. Idempotent.\n * Call from `registerRuntimeLifecycle({ cleanup })` in the host plugin.\n */\n async dispose(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n if (this.idleSweepTimer) {\n clearInterval(this.idleSweepTimer);\n this.idleSweepTimer = undefined;\n }\n if (this.retrySweepTimer) {\n clearInterval(this.retrySweepTimer);\n this.retrySweepTimer = undefined;\n }\n await Promise.allSettled(Array.from(this.connections.values()).map((c) => c.close()));\n this.connections.clear();\n }\n\n private startIdleSweep(): void {\n this.idleSweepTimer = setInterval(() => {\n void this.sweepIdle().catch((err: unknown) => {\n this.logger?.warn('[mcp-bundler] idle sweep error', {\n err: err instanceof Error ? err.message : String(err),\n });\n });\n }, this.idleSweepIntervalMs);\n // Don't keep the host process alive just for the sweep.\n if (typeof this.idleSweepTimer === 'object' && 'unref' in this.idleSweepTimer) {\n (this.idleSweepTimer as { unref: () => void }).unref();\n }\n }\n\n private startRetrySweep(): void {\n this.retrySweepTimer = setInterval(() => {\n // Guard against overlap: a slow retry (spawn/handshake) must not stack up\n // if the previous sweep is still resolving.\n if (this.retrySweepInFlight) return;\n this.retrySweepInFlight = true;\n void this.retryFailed()\n .then((attempted) => {\n if (attempted.length === 0) return;\n const healed = attempted.filter((s) => s.connected);\n const stillDown = attempted.filter((s) => !s.connected);\n this.logger?.debug('[mcp-bundler] retry sweep', {\n attempted: attempted.length,\n healed: healed.length,\n stillDown: stillDown.length,\n });\n for (const s of healed) {\n this.logger?.info(`[mcp-bundler] server \"${s.name}\" self-healed on retry sweep`, {\n toolCount: s.toolCount,\n });\n }\n })\n .catch((err: unknown) => {\n this.logger?.warn('[mcp-bundler] retry sweep error', {\n err: err instanceof Error ? err.message : String(err),\n });\n })\n .finally(() => {\n this.retrySweepInFlight = false;\n });\n }, this.retrySweepIntervalMs);\n // Don't keep the host process alive just for the sweep.\n if (typeof this.retrySweepTimer === 'object' && 'unref' in this.retrySweepTimer) {\n (this.retrySweepTimer as { unref: () => void }).unref();\n }\n }\n\n private async sweepIdle(): Promise<void> {\n if (this.idleTtlMs <= 0) return;\n const targets: Connection[] = [];\n for (const conn of this.connections.values()) {\n if (conn.isConnected() && conn.idleSinceMs() > this.idleTtlMs) {\n targets.push(conn);\n }\n }\n if (targets.length === 0) return;\n this.logger?.debug(`[mcp-bundler] reaping ${targets.length.toString()} idle server(s)`);\n await Promise.allSettled(targets.map((c) => c.close()));\n }\n}\n\nfunction checkedDuration(value: number, label: string, max = 86_400_000): number {\n if (!Number.isSafeInteger(value) || value < 0 || value > max) {\n throw new Error(`McpBundler ${label} must be an integer from 0 to ${max.toString()}`);\n }\n return value;\n}\n","import {\n closeSync,\n constants,\n fchmodSync,\n fstatSync,\n fsyncSync,\n lstatSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n watch,\n writeFileSync,\n type FSWatcher,\n} from 'node:fs';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { Logger, McpServerConfig, StdioServerConfig, RemoteServerConfig, McpTransportKind } from './types.js';\nimport { validateServerConfig, validateServerCount, validateServerId } from './validation.js';\n\n/**\n * Where a server entry came from. Used by `removeServersByOwner` so an\n * integration uninstall can drop only its own entries without touching\n * `cli`-owned (e.g. `alfe-platform`) or `manual`-owned (user-added) ones.\n */\nexport type ServerOwner = 'cli' | `integration:${string}` | 'manual';\n\ninterface StoredServerCommon {\n /** Where the entry came from — controls bulk-removal semantics. */\n owner: ServerOwner;\n /** ISO timestamp of first registration; preserved across updates. */\n addedAt: string;\n /** Optional semver of the providing package (e.g. `@alfe.ai/mcp-server` for `alfe-platform`). Used for drift detection on CLI upgrade. */\n version?: string;\n}\n\nexport type StoredServerEntry =\n | (StoredServerCommon & { transport: 'stdio' } & StdioServerConfig)\n | (StoredServerCommon & { transport: 'sse' | 'streamable-http' } & RemoteServerConfig);\n\nexport interface StoreSchema {\n servers: Record<string, StoredServerEntry>;\n config: {\n sessionIdleTtlMs?: number;\n };\n /**\n * Server names this manager has written into `openclaw.json#mcp.servers.*`.\n * Used to compute the mirror-write diff without re-reading openclaw.json\n * (which would be a second source of truth). Foreign keys not listed here\n * are preserved across mirror writes.\n */\n _ownedOpenclawKeys: string[];\n}\n\nconst DEFAULT_STORE_DIR = join(homedir(), '.alfe', 'mcp');\nconst DEFAULT_STORE_PATH = join(DEFAULT_STORE_DIR, 'servers.json');\n\n/** Inter-process lock tunings — exported as constants so tests can override. */\nconst LOCK_WAIT_MS = 5_000;\nconst LOCK_RETRY_INTERVAL_MS = 25;\nconst LOCK_STALE_MS = 10_000;\nconst MAX_STORE_BYTES = 1024 * 1024;\n\nexport interface StoreOptions {\n /** Absolute path to the store file. Defaults to `~/.alfe/mcp/servers.json`. */\n path?: string;\n logger?: Logger;\n}\n\n/**\n * On-disk source of truth for the bundler's configured servers.\n *\n * Mutations go through `update()` (read-modify-write with atomic\n * temp+rename) so a concurrent writer (e.g. two `alfe mcp add` invocations\n * racing) can't lose data — the second writer reads the first's state.\n *\n * Schema is owner-tagged so `removeServersByOwner` can implement\n * integration uninstall without touching CLI-owned or manual entries.\n */\nexport class Store {\n private readonly storePath: string;\n private readonly logger?: Logger;\n private watcher?: FSWatcher;\n private watcherListeners = new Set<() => void>();\n private rewatchTimer?: NodeJS.Timeout;\n\n constructor(opts: StoreOptions = {}) {\n this.storePath = opts.path ?? DEFAULT_STORE_PATH;\n if (!isAbsolute(this.storePath)) throw new Error('Store path must be absolute');\n this.logger = opts.logger;\n }\n\n get path(): string {\n return this.storePath;\n }\n\n read(): StoreSchema {\n let fd = -1;\n try {\n try {\n fd = openSync(this.storePath, constants.O_RDONLY | constants.O_NOFOLLOW);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return cloneEmpty();\n throw err;\n }\n const stat = fstatSync(fd);\n if (!stat.isFile()) throw new Error('store path is not a regular file');\n if (typeof process.getuid === 'function' && stat.uid !== process.getuid()) {\n throw new Error('store file is not owned by the current user');\n }\n if ((stat.mode & 0o077) !== 0) {\n // Safely migrate a legacy current-user store before reading secrets.\n fchmodSync(fd, 0o600);\n }\n if (stat.size > MAX_STORE_BYTES) {\n throw new Error(`store exceeds the ${MAX_STORE_BYTES.toString()} byte limit`);\n }\n const raw = readFileSync(fd, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n return normalize(parsed);\n } catch (err) {\n this.logger?.warn('[mcp-bundler/store] rejected unreadable or invalid store', {\n err: errMsg(err),\n path: this.storePath,\n });\n throw new Error(`Store.read: rejected ${this.storePath}: ${errMsg(err)}`, { cause: err });\n } finally {\n if (fd >= 0) closeSync(fd);\n }\n }\n\n /**\n * Read-modify-write with atomic temp+rename, guarded by an\n * inter-process lock file. Caller passes a pure function that\n * produces the next state; this serialises the mutation to disk in\n * one rename, which is atomic on POSIX and on Windows when the\n * target path is on the same volume.\n *\n * The lock guards the read-then-rename window so two processes\n * (e.g. two `alfe mcp add` shells, or the CLI racing the daemon)\n * can't drop each other's writes. The lock file is at\n * `<storePath>.lock`; locks whose recorded writer process is no longer\n * alive are reclaimed so a crashed writer doesn't wedge the store.\n *\n * Pure-function shape (instead of a `read()` then `write(next)`\n * pair) intentionally — it keeps the read-modify-write contract\n * local to each caller so two updates back-to-back never see each\n * other's partial state.\n */\n update(fn: (cur: StoreSchema) => StoreSchema): StoreSchema {\n mkdirSync(dirname(this.storePath), { recursive: true, mode: 0o700 });\n const release = this.acquireLock();\n try {\n const cur = this.read();\n const next = normalize(fn(cur));\n const payload = JSON.stringify(next, null, 2);\n if (Buffer.byteLength(payload, 'utf8') > MAX_STORE_BYTES) {\n throw new Error(`Store.update: result exceeds the ${MAX_STORE_BYTES.toString()} byte limit`);\n }\n const tempPath = `${this.storePath}.${String(process.pid)}.${randomUUID()}.tmp`;\n let tempFd = -1;\n try {\n tempFd = openSync(tempPath, 'wx', 0o600);\n writeFileSync(tempFd, payload, { encoding: 'utf8' });\n fsyncSync(tempFd);\n closeSync(tempFd);\n tempFd = -1;\n renameSync(tempPath, this.storePath);\n this.fsyncParentDirectory();\n } catch (err) {\n if (tempFd >= 0) closeSync(tempFd);\n try {\n unlinkSync(tempPath);\n } catch {\n // Best-effort cleanup; the random exclusive name cannot collide.\n }\n throw err;\n }\n return next;\n } finally {\n release();\n }\n }\n\n /**\n * Acquire an inter-process file lock by atomically creating a\n * sentinel via `openSync(lockPath, 'wx')`. Waits with bounded\n * backoff up to `LOCK_WAIT_MS`. A structured lock is reclaimed only when\n * its writer process is no longer alive; age alone cannot steal a lock\n * from a slow but valid writer. Old malformed/legacy locks retain a\n * conservative age fallback.\n *\n * Returns the release function. Single-process callers are\n * unaffected — re-entering the same process spins briefly while\n * the prior call's `finally` runs.\n */\n private acquireLock(): () => void {\n const lockPath = `${this.storePath}.lock`;\n const deadline = Date.now() + LOCK_WAIT_MS;\n let fd = -1;\n let heldDevice = -1;\n let heldInode = -1;\n for (;;) {\n try {\n fd = openSync(lockPath, 'wx', 0o600);\n const token = randomUUID();\n writeFileSync(fd, JSON.stringify({ pid: process.pid, token, createdAt: new Date().toISOString() }), 'utf8');\n fsyncSync(fd);\n const stat = fstatSync(fd);\n heldDevice = stat.dev;\n heldInode = stat.ino;\n break;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'EEXIST') throw err;\n const stale = this.inspectStaleLock(lockPath);\n if (stale) {\n try {\n const current = lstatSync(lockPath);\n if (current.dev === stale.device && current.ino === stale.inode) unlinkSync(lockPath);\n } catch {\n // Another process may have just released it — fall through and retry.\n }\n continue;\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `Store.update: timed out waiting for ${lockPath} (held by another writer or stale lock)`,\n );\n }\n sleepSync(LOCK_RETRY_INTERVAL_MS);\n }\n }\n const held = fd;\n return () => {\n try {\n closeSync(held);\n } catch {\n // ignore — the unlink is what releases the lock for the next writer.\n }\n try {\n const current = lstatSync(lockPath);\n if (current.dev === heldDevice && current.ino === heldInode) unlinkSync(lockPath);\n } catch {\n // ignore — already unlinked; inode identity prevents deleting a successor lock.\n }\n };\n }\n\n private inspectStaleLock(lockPath: string): { device: number; inode: number } | undefined {\n let fd = -1;\n let modifiedAt: number | undefined;\n let device: number | undefined;\n let inode: number | undefined;\n try {\n fd = openSync(lockPath, constants.O_RDONLY | constants.O_NOFOLLOW);\n const stat = fstatSync(fd);\n modifiedAt = stat.mtimeMs;\n device = stat.dev;\n inode = stat.ino;\n if (!stat.isFile() || stat.size > 4096) {\n return Date.now() - stat.mtimeMs > LOCK_STALE_MS ? { device, inode } : undefined;\n }\n const parsed: unknown = JSON.parse(readFileSync(fd, 'utf8'));\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return Date.now() - stat.mtimeMs > LOCK_STALE_MS ? { device, inode } : undefined;\n }\n const pid = (parsed as { pid?: unknown }).pid;\n if (!Number.isSafeInteger(pid) || (pid as number) <= 0) {\n return Date.now() - stat.mtimeMs > LOCK_STALE_MS ? { device, inode } : undefined;\n }\n return !processIsAlive(pid as number) ? { device, inode } : undefined;\n } catch {\n return modifiedAt !== undefined && device !== undefined && inode !== undefined &&\n Date.now() - modifiedAt > LOCK_STALE_MS\n ? { device, inode }\n : undefined;\n } finally {\n if (fd >= 0) closeSync(fd);\n }\n }\n\n private fsyncParentDirectory(): void {\n let fd = -1;\n try {\n fd = openSync(dirname(this.storePath), constants.O_RDONLY);\n fsyncSync(fd);\n } catch {\n // Some platforms/filesystems do not support fsync on directories.\n } finally {\n if (fd >= 0) closeSync(fd);\n }\n }\n\n /**\n * Watch the store file for external changes (e.g. another `alfe mcp add`\n * shelling out from a separate process). Returns an unsubscribe fn.\n *\n * Coalesces bursts via a 50 ms debounce — editors and atomic-rename\n * writers commonly fire multiple events per logical save.\n */\n watch(cb: () => void): () => void {\n this.watcherListeners.add(cb);\n this.ensureWatcher();\n return () => {\n this.watcherListeners.delete(cb);\n if (this.watcherListeners.size === 0) this.disposeWatcher();\n };\n }\n\n dispose(): void {\n this.watcherListeners.clear();\n this.disposeWatcher();\n }\n\n private ensureWatcher(): void {\n if (this.watcher) return;\n mkdirSync(dirname(this.storePath), { recursive: true, mode: 0o700 });\n // Some platforms / atomic renames make a per-file watch flaky after\n // a rename; watching the parent directory and filtering by basename\n // is more robust.\n const dir = dirname(this.storePath);\n const basename = this.storePath.slice(dir.length + 1);\n let pending: NodeJS.Timeout | undefined;\n const fire = (): void => {\n pending = undefined;\n for (const cb of this.watcherListeners) {\n try {\n cb();\n } catch (err) {\n this.logger?.warn('[mcp-bundler/store] watcher listener threw', { err: errMsg(err) });\n }\n }\n };\n try {\n this.watcher = watch(dir, (_event, fn) => {\n if (fn !== basename) return;\n if (pending) clearTimeout(pending);\n pending = setTimeout(fire, 50);\n });\n this.watcher.on('error', (err) => {\n this.logger?.warn('[mcp-bundler/store] watcher error; retrying in 1s', { err: errMsg(err) });\n this.disposeWatcher();\n if (!this.rewatchTimer && this.watcherListeners.size > 0) {\n this.rewatchTimer = setTimeout(() => {\n this.rewatchTimer = undefined;\n this.ensureWatcher();\n }, 1000);\n this.rewatchTimer.unref();\n }\n });\n } catch (err) {\n this.logger?.warn('[mcp-bundler/store] failed to start watcher', { err: errMsg(err) });\n }\n }\n\n private disposeWatcher(): void {\n if (this.watcher) {\n try {\n this.watcher.close();\n } catch {\n // close throws on already-disposed watchers; ignore.\n }\n this.watcher = undefined;\n }\n if (this.rewatchTimer) {\n clearTimeout(this.rewatchTimer);\n this.rewatchTimer = undefined;\n }\n }\n}\n\nexport function defaultStorePath(): string {\n return DEFAULT_STORE_PATH;\n}\n\n/**\n * One-way launch-identity fingerprint for cache invalidation across IPC.\n * Store entries contain credentials in env/headers, so consumers that only\n * need equality receive this digest rather than the executable configuration.\n */\nexport function serverLaunchFingerprint(entry: StoredServerEntry): string {\n const identity = {\n config: toServerConfig(entry),\n version: entry.version ?? null,\n };\n return `sha256:${createHash('sha256').update(stableJson(identity)).digest('hex')}`;\n}\n\n/** Pull the runtime config (transport + transport-specific fields) out of a stored entry. */\nexport function toServerConfig(entry: StoredServerEntry): McpServerConfig {\n if (entry.transport === 'stdio') {\n const { command, args, env, cwd, connectionTimeoutMs } = entry;\n const cfg: StdioServerConfig = { command };\n if (args) cfg.args = [...args];\n if (env) cfg.env = { ...env };\n if (cwd) cfg.cwd = cwd;\n if (connectionTimeoutMs !== undefined) cfg.connectionTimeoutMs = connectionTimeoutMs;\n return validateServerConfig(cfg);\n }\n const { url, transport, headers, connectionTimeoutMs } = entry;\n const cfg: RemoteServerConfig = { url, transport };\n if (headers) cfg.headers = { ...headers };\n if (connectionTimeoutMs !== undefined) cfg.connectionTimeoutMs = connectionTimeoutMs;\n return validateServerConfig(cfg);\n}\n\n/** Build a stored entry from a runtime config + ownership metadata. */\nexport function toStoredEntry(\n config: McpServerConfig,\n meta: { owner: ServerOwner; transport?: McpTransportKind; version?: string; addedAt?: string },\n): StoredServerEntry {\n validateOwner(meta.owner);\n const checked = validateServerConfig(config);\n const addedAt = meta.addedAt ?? new Date().toISOString();\n validateTimestamp(addedAt, 'addedAt');\n if (meta.version !== undefined) validateVersion(meta.version);\n if ('command' in checked) {\n return {\n transport: 'stdio',\n owner: meta.owner,\n addedAt,\n ...(meta.version !== undefined ? { version: meta.version } : {}),\n ...checked,\n };\n }\n const transport = meta.transport ?? checked.transport ?? 'sse';\n if (transport === 'stdio') {\n throw new Error('toStoredEntry: transport=stdio specified but config is remote-shaped');\n }\n return {\n owner: meta.owner,\n addedAt,\n ...(meta.version !== undefined ? { version: meta.version } : {}),\n ...checked,\n transport,\n };\n}\n\nfunction cloneEmpty(): StoreSchema {\n return { servers: {}, config: {}, _ownedOpenclawKeys: [] };\n}\n\nfunction normalize(raw: unknown): StoreSchema {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('store root must be an object');\n const r = raw as Record<string, unknown>;\n const rawServers = r.servers;\n if (!rawServers || typeof rawServers !== 'object' || Array.isArray(rawServers)) {\n throw new Error('store.servers must be an object');\n }\n const serverEntries = Object.entries(rawServers);\n validateServerCount(serverEntries.length);\n const servers: Record<string, StoredServerEntry> = {};\n for (const [id, rawEntry] of serverEntries) {\n validateServerId(id);\n if (!rawEntry || typeof rawEntry !== 'object' || Array.isArray(rawEntry)) {\n throw new Error(`store server \"${id}\" must be an object`);\n }\n const entry = rawEntry as Partial<StoredServerEntry>;\n validateOwner(entry.owner);\n validateTimestamp(entry.addedAt, `store server \"${id}\" addedAt`);\n if (entry.version !== undefined) validateVersion(entry.version);\n if (!['stdio', 'sse', 'streamable-http'].includes(String(entry.transport))) {\n throw new Error(`store server \"${id}\" has an invalid transport`);\n }\n const runtime = entry.transport === 'stdio'\n ? validateServerConfig(entry, `store server \"${id}\"`)\n : validateServerConfig({ ...entry, transport: entry.transport }, `store server \"${id}\"`);\n servers[id] = toStoredEntry(runtime, {\n owner: entry.owner,\n transport: entry.transport,\n addedAt: entry.addedAt,\n version: entry.version,\n });\n }\n const rawConfig: unknown = r.config ?? {};\n if (!rawConfig || typeof rawConfig !== 'object' || Array.isArray(rawConfig)) {\n throw new Error('store.config must be an object');\n }\n const config: StoreSchema['config'] = {};\n const ttl = (rawConfig as Record<string, unknown>).sessionIdleTtlMs;\n if (ttl !== undefined) {\n if (typeof ttl !== 'number' || !Number.isSafeInteger(ttl) || ttl < 0 || ttl > 86_400_000) {\n throw new Error('store.config.sessionIdleTtlMs must be an integer from 0 to 86400000');\n }\n config.sessionIdleTtlMs = ttl;\n }\n const rawOwned = r._ownedOpenclawKeys;\n if (rawOwned !== undefined && !Array.isArray(rawOwned)) {\n throw new Error('store._ownedOpenclawKeys must be an array');\n }\n const ownedValues: unknown[] = rawOwned ?? [];\n const owned = [...new Set(\n ownedValues.map((value) => validateServerId(value, 'store._ownedOpenclawKeys entry')),\n )];\n validateServerCount(owned.length);\n return {\n servers,\n config,\n _ownedOpenclawKeys: owned,\n };\n}\n\nfunction validateOwner(owner: unknown): asserts owner is ServerOwner {\n if (owner === 'cli' || owner === 'manual') return;\n if (typeof owner === 'string' && owner.startsWith('integration:')) {\n validateServerId(owner.slice('integration:'.length), 'integration owner id');\n return;\n }\n throw new Error('server owner must be cli, manual, or integration:<id>');\n}\n\nfunction validateTimestamp(value: unknown, label: string): asserts value is string {\n if (typeof value !== 'string' || !Number.isFinite(Date.parse(value))) {\n throw new Error(`${label} must be an ISO timestamp`);\n }\n}\n\nfunction validateVersion(value: unknown): asserts value is string {\n if (typeof value !== 'string' || !/^[0-9A-Za-z][0-9A-Za-z.+-]{0,127}$/.test(value)) {\n throw new Error('server version is invalid');\n }\n}\n\nfunction processIsAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ESRCH';\n }\n}\n\nconst sleepBuffer = new Int32Array(new SharedArrayBuffer(4));\nfunction sleepSync(ms: number): void {\n Atomics.wait(sleepBuffer, 0, 0, ms);\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n return `{${Object.keys(record)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`)\n .join(',')}}`;\n }\n return value === undefined ? 'null' : JSON.stringify(value);\n}\n","import type { McpBundler } from './bundler.js';\nimport { Store, toServerConfig, toStoredEntry, type ServerOwner, type StoredServerEntry } from './store.js';\nimport type { Logger, McpServerConfig, McpServerStatus, McpTransportKind } from './types.js';\nimport { validateServerId } from './validation.js';\n\nexport interface ManagerOptions {\n /** Pre-constructed store. If omitted, one is built with default options. */\n store?: Store;\n logger?: Logger;\n}\n\nexport interface AddServerOptions {\n /** Required — flat-namespace key under the bundler store. */\n id: string;\n /** Marks ownership for bulk removal. Defaults to `manual`. */\n owner?: ServerOwner;\n /** Semver of the providing package; used for CLI version-drift detection. */\n version?: string;\n /** Explicit transport hint for remote configs. Defaults to inferring from `config`. */\n transport?: McpTransportKind;\n /** Propagate live replacement errors when the caller owns a retryable authority checkpoint. */\n strictReconcile?: boolean;\n}\n\n/**\n * Bundler manager — owns the `~/.alfe/mcp/servers.json` store and surfaces a\n * small CRUD API the CLI and integration applier both call into.\n *\n * Single source of truth: every consumer (daemon-hosted bundler, CLI `alfe mcp\n * list`, integration uninstall) reads from this store. Openclaw.json is no\n * longer kept in sync — the daemon hosts the bundler children and the\n * openclaw plugin reaches them via IPC, so the openclaw.json mirror became\n * dead weight and an active source of duplicate spawning on claude-cli /\n * codex-cli backends.\n *\n * Call `loadIntoBundler(bundler)` once at daemon startup to wire the store\n * into a live `McpBundler` — subsequent store mutations (including those\n * landed by other processes via the file watcher) re-reconcile automatically.\n */\nexport class Manager {\n private readonly store: Store;\n private readonly ownsStore: boolean;\n private readonly logger?: Logger;\n private bundler?: McpBundler;\n private changeListeners = new Set<() => void>();\n private storeUnsubscribe?: () => void;\n\n constructor(opts: ManagerOptions = {}) {\n this.ownsStore = opts.store === undefined;\n this.store = opts.store ?? new Store({ logger: opts.logger });\n this.logger = opts.logger;\n }\n\n /** Direct accessor — handy for tests and the CLI's `alfe mcp list`. */\n getStore(): Store {\n return this.store;\n }\n\n /**\n * Register or overwrite a server entry. Mutation lands in the store\n * synchronously; if a bundler has been attached via `loadIntoBundler`,\n * it is re-reconciled BEFORE `onChange` listeners fire. A reconcile error is\n * logged and does not roll back the durable store mutation, but listeners do\n * not fire against stale live state. The ordering is load-bearing: the daemon's `onChange`\n * handler warms the bundler's current connections, so the just-added\n * server must already have its Connection object or it is never warmed.\n */\n async addServer(config: McpServerConfig, opts: AddServerOptions): Promise<void> {\n validateServerId(opts.id, 'Manager.addServer id');\n const owner = opts.owner ?? 'manual';\n this.store.update((cur) => {\n const previousAddedAt = lookupAddedAt(cur.servers, opts.id);\n const entry = toStoredEntry(config, {\n owner,\n transport: opts.transport,\n version: opts.version,\n addedAt: previousAddedAt,\n });\n return {\n ...cur,\n servers: { ...cur.servers, [opts.id]: entry },\n };\n });\n if (opts.strictReconcile) {\n await this.reconcileBundler();\n this.fireChange();\n } else if (await this.reconcileBundlerLogged()) this.fireChange();\n }\n\n /**\n * Remove a single server entry. No-op if the id isn't in the store.\n * Refuses to remove an entry whose owner doesn't match `expectedOwner`\n * when supplied — the CLI uses this to guard `alfe mcp remove` from\n * accidentally clobbering integration- or cli-owned entries.\n */\n async removeServer(id: string, opts: { expectedOwner?: ServerOwner; strictReconcile?: boolean } = {}): Promise<boolean> {\n validateServerId(id, 'Manager.removeServer id');\n const outcome = { removed: false };\n this.store.update((cur) => {\n const existing = lookupEntry(cur.servers, id);\n if (!existing) return cur;\n if (opts.expectedOwner && existing.owner !== opts.expectedOwner) {\n throw new Error(\n `Manager.removeServer: server \"${id}\" is owned by \"${existing.owner}\", not \"${opts.expectedOwner}\"`,\n );\n }\n outcome.removed = true;\n return {\n ...cur,\n servers: Object.fromEntries(Object.entries(cur.servers).filter(([key]) => key !== id)),\n };\n });\n if (!outcome.removed && !opts.strictReconcile) return false;\n if (opts.strictReconcile) {\n // A retried deletion may already be durable while the old child still exists.\n await this.reconcileBundler();\n this.fireChange();\n } else if (await this.reconcileBundlerLogged()) this.fireChange();\n return outcome.removed;\n }\n\n /** Drop every entry whose owner matches — used by integration uninstall. */\n async removeServersByOwner(owner: ServerOwner): Promise<string[]> {\n const removed: string[] = [];\n this.store.update((cur) => {\n const next: Record<string, StoredServerEntry> = {};\n for (const [id, entry] of Object.entries(cur.servers)) {\n if (entry.owner === owner) {\n removed.push(id);\n } else {\n next[id] = entry;\n }\n }\n if (removed.length === 0) return cur;\n return { ...cur, servers: next };\n });\n if (removed.length > 0) {\n if (await this.reconcileBundlerLogged()) this.fireChange();\n }\n return removed;\n }\n\n /** Read-only snapshot for `alfe mcp list` and similar UIs. */\n listServers(): { id: string; entry: StoredServerEntry }[] {\n const snap = this.store.read();\n return Object.entries(snap.servers).map(([id, entry]) => ({ id, entry }));\n }\n\n /**\n * Live connection status per server from the attached bundler. Empty when\n * no bundler is attached (e.g. a CLI-only manager). Lets callers show\n * whether each registered server actually connected and how many tools it\n * advertises, instead of only the stored config.\n */\n serverStatuses(): McpServerStatus[] {\n return this.bundler ? this.bundler.statuses() : [];\n }\n\n /**\n * Reconcile the bundler against the current store (so a just-added entry\n * has a connection object) then eagerly connect ONE server and return its\n * status. Used by the daemon to CONFIRM an `alfe mcp add` actually connected\n * before replying to the agent — turning the fire-and-forget warm into a\n * result the caller can report (\"connected, N tools\" or the real error).\n *\n * Returns `null` when no bundler is attached or the id isn't present; never\n * throws (a connect failure is carried in the returned status).\n */\n async warmServer(id: string, timeoutMs?: number): Promise<McpServerStatus | null> {\n if (!this.bundler) return null;\n try {\n validateServerId(id, 'Manager.warmServer id');\n await this.reconcileBundler();\n return (await this.bundler.warmServer(id, timeoutMs)) ?? null;\n } catch (err) {\n this.logger?.warn('[mcp-bundler/manager] warm reconcile failed', { err: errMsg(err) });\n return null;\n }\n }\n\n /**\n * Push the current store contents into a bundler instance (which owns\n * connections / tools). Wires up a store watcher so external mutations\n * (e.g. another shell running `alfe mcp add`) re-reconcile.\n */\n async loadIntoBundler(bundler: McpBundler): Promise<void> {\n this.bundler = bundler;\n await this.reconcileBundler();\n this.storeUnsubscribe ??= this.store.watch(() => {\n void this.reconcileBundler().catch((err: unknown) => {\n this.logger?.warn('[mcp-bundler/manager] watcher reconcile failed', { err: errMsg(err) });\n });\n });\n }\n\n /** Subscribe to store mutations. Returns an unsubscribe fn. */\n onChange(cb: () => void): () => void {\n this.changeListeners.add(cb);\n return () => {\n this.changeListeners.delete(cb);\n };\n }\n\n /**\n * Detach from the bundler and stop watching the store. Safe to call\n * multiple times. An injected Store remains owned by its caller; a Store\n * constructed by this manager is disposed here.\n */\n async dispose(): Promise<void> {\n if (this.storeUnsubscribe) {\n this.storeUnsubscribe();\n this.storeUnsubscribe = undefined;\n }\n if (this.ownsStore) this.store.dispose();\n this.changeListeners.clear();\n this.bundler = undefined;\n return Promise.resolve();\n }\n\n /**\n * Awaited by every mutator so `onChange` listeners observe a bundler\n * that already contains the mutation. Reconcile failures are logged and\n * return false so callers preserve the durable mutation without notifying\n * listeners against stale derived state.\n */\n private async reconcileBundlerLogged(): Promise<boolean> {\n if (!this.bundler) return true;\n try {\n await this.reconcileBundler();\n return true;\n } catch (err) {\n this.logger?.warn('[mcp-bundler/manager] bundler reconcile failed', { err: errMsg(err) });\n return false;\n }\n }\n\n private async reconcileBundler(): Promise<void> {\n if (!this.bundler) return;\n const snap = this.store.read();\n const servers: Record<string, McpServerConfig> = {};\n for (const [id, entry] of Object.entries(snap.servers)) {\n servers[id] = toServerConfig(entry);\n }\n await this.bundler.reconcile(servers);\n }\n\n private fireChange(): void {\n for (const cb of this.changeListeners) {\n try {\n cb();\n } catch (err) {\n this.logger?.warn('[mcp-bundler/manager] onChange listener threw', { err: errMsg(err) });\n }\n }\n }\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Indexed access on `Record<string, T>` returns `T` (not `T | undefined`)\n * unless `noUncheckedIndexedAccess` is set in tsconfig. These helpers\n * make the optional-ness explicit so the lint rules that hate\n * always-truthy conditionals stop firing on real lookups.\n */\nfunction lookupEntry(\n servers: Record<string, StoredServerEntry>,\n id: string,\n): StoredServerEntry | undefined {\n return Object.hasOwn(servers, id) ? servers[id] : undefined;\n}\n\nfunction lookupAddedAt(servers: Record<string, StoredServerEntry>, id: string): string | undefined {\n const entry = lookupEntry(servers, id);\n return entry ? entry.addedAt : undefined;\n}\n","/**\n * Pattern A validator — locks the \"explicit selector arg\" contract for\n * credential-touching tools across the openclaw-* plugin family.\n *\n * Background\n * ----------\n * Pattern A says every credential-touching tool on a multi-account-capable\n * provider MUST take a required selector arg in its JSON Schema so the LLM\n * picks the account deliberately. The reference implementation lives in\n * `@alfe.ai/openclaw-google` (`google_run_command` / `google_disconnect_\n * account` both require `email`). PR 7 of channels-and-credential-driven-\n * integrations sweeps the same shape across notion / xero / myob.\n *\n * Why a validator\n * ---------------\n * The contract is easy to break by accident — a new tool gets added, the\n * selector arg gets forgotten, the LLM silently dispatches to whichever\n * account was loaded first. There's no runtime safety net once the plugin\n * is published. This validator runs in plugin build steps (or CI) and\n * fails the build if a tool that declares itself credential-touching\n * doesn't carry the selector.\n *\n * Scope of this file\n * ------------------\n * Pure functions — no I/O. Plugin packages call into these helpers from\n * their own build scripts (e.g. `pnpm build` or a dedicated lint task) and\n * pass in their `ToolDef[]` or `McpToolDescriptor[]` collection. The\n * validator does NOT know how to read manifests or files — it only checks\n * the shape of the in-memory descriptor list. Wiring is up to each plugin.\n *\n * Consumers\n * ---------\n * - `@alfe.ai/myob-mcp` — direct MCP, explicit TypeBox schemas.\n * - `@alfe.ai/notion-mcp` — proxy MCP, injects selector at runtime.\n * - `@alfe.ai/xero-mcp` — proxy MCP, injects selector at runtime.\n * - `@alfe.ai/openclaw-google` — already compliant; can opt-in for regression.\n *\n * Future\n * ------\n * When PR 7-deferred lands (atlassian / github / microsoft openclaw\n * packages), they hook into the same validator. The atlassian / github\n * cases will likely run the validator over the proxied child server's\n * `listTools()` response after schema-injection, to confirm the injection\n * actually landed on every tool.\n */\n\nimport type { McpToolDescriptor } from './types.js';\n\n// ── Public types ────────────────────────────────────────────\n\n/**\n * A tool descriptor that the validator can inspect. Plugins can pass\n * either {@link McpToolDescriptor} (for proxy plugins surfacing child\n * tools) or a leaner local shape (for direct-MCP plugins). Both come\n * down to a tool name and a JSON Schema parameter object.\n */\nexport interface ValidatableTool {\n /** Tool name as the LLM sees it (post-namespacing). */\n name: string;\n /** JSON Schema for tool parameters (the `inputSchema`). */\n parameters: Record<string, unknown>;\n}\n\nexport interface PatternAOptions {\n /**\n * The required selector property name. Provider-specific (Google uses\n * `email`; Notion will use `workspaceId`; Xero will use `xeroTenantId`;\n * MYOB will use `myobBusinessId`). Plugins MAY support more than one\n * acceptable name — pass an array.\n */\n selector: string | readonly string[];\n /**\n * Tool names exempt from the selector requirement — typically the\n * `list_accounts` discovery tool and any pure-utility tools that don't\n * touch credentials. Match is exact (post-namespacing).\n */\n exempt?: readonly string[];\n}\n\nexport interface PatternAViolation {\n tool: string;\n reason:\n | 'missing-selector-property'\n | 'selector-not-required'\n | 'selector-property-not-string';\n detail: string;\n}\n\n// ── Core check ───────────────────────────────────────────────\n\n/**\n * Validate that every non-exempt tool's JSON Schema declares the selector\n * property AND lists it in `required`. Returns the full set of violations\n * so the caller can report them all in one pass — failing fast on the\n * first one tends to hide cascading bugs in real plugins.\n *\n * The check is intentionally schema-shape-only — it does NOT execute the\n * tool, call the LLM, or talk to the cloud. It's a fast structural pass\n * suitable for build-time use.\n */\nexport function checkPatternA(\n tools: readonly ValidatableTool[],\n options: PatternAOptions,\n): PatternAViolation[] {\n const selectorNames = typeof options.selector === \"string\"\n ? [options.selector]\n : options.selector;\n if (selectorNames.length === 0 || selectorNames.some((name) => typeof name !== 'string' || name.length === 0)) {\n throw new Error('Pattern A selector must contain at least one non-empty property name');\n }\n const exempt = new Set(options.exempt ?? []);\n const violations: PatternAViolation[] = [];\n\n for (const tool of tools) {\n if (exempt.has(tool.name)) continue;\n\n const schema = isRecord(tool.parameters) ? tool.parameters : {};\n const rawProperties = schema.properties;\n const properties = isRecord(rawProperties) ? rawProperties : {};\n const required = Array.isArray(schema.required)\n ? schema.required.filter((value): value is string => typeof value === 'string')\n : [];\n const present = selectorNames.filter((name) => Object.hasOwn(properties, name));\n\n if (present.length === 0) {\n violations.push({\n tool: tool.name,\n reason: 'missing-selector-property',\n detail: `expected one of [${selectorNames.join(', ')}] in inputSchema.properties`,\n });\n continue;\n }\n\n const requiredSelectors = present.filter((name) => required.includes(name));\n if (requiredSelectors.length === 0) {\n violations.push({\n tool: tool.name,\n reason: 'selector-not-required',\n detail: `selector [${present.join(', ')}] present in properties but missing from inputSchema.required`,\n });\n continue;\n }\n\n const validSelector = requiredSelectors.find((name) => {\n const property = properties[name];\n return isRecord(property) && property.type === 'string';\n });\n if (!validSelector) {\n const foundTypes = requiredSelectors.map((name) => {\n const property = properties[name];\n return `${name}=${JSON.stringify(isRecord(property) ? property.type : undefined)}`;\n });\n violations.push({\n tool: tool.name,\n reason: 'selector-property-not-string',\n detail: `at least one required selector must be JSON Schema type=string (found ${foundTypes.join(', ')})`,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * Thin wrapper that throws an Error listing every violation if any are\n * present. Convenient for build scripts that want a single guard call.\n */\nexport function assertPatternA(\n tools: readonly ValidatableTool[],\n options: PatternAOptions,\n): void {\n const violations = checkPatternA(tools, options);\n if (violations.length === 0) return;\n const lines = violations.map((violation) => ` - [${violation.reason}] ${violation.tool}: ${violation.detail}`);\n throw new Error(\n `Pattern A validation failed for ${String(violations.length)} tool(s):\\n${lines.join('\\n')}`,\n );\n}\n\n/**\n * Cast an {@link McpToolDescriptor} (proxy-plugin shape) to the leaner\n * {@link ValidatableTool} the validator accepts. Useful for proxy\n * plugins that already maintain a `cachedTools: McpToolDescriptor[]`\n * collection.\n */\nexport function fromMcpDescriptor(descriptor: McpToolDescriptor): ValidatableTool {\n return { name: descriptor.prefixed, parameters: descriptor.parameters };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/mcp-bundler",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Provider-agnostic MCP server bundler — connects to N MCP servers (stdio/SSE/streamable-http), aggregates their tools with namespacing, exposes a unified callable surface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|