UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

113 lines (112 loc) 4.19 kB
import { a as normalizeEnvVarKey, i as isDangerousHostInheritedEnvVarName, r as isDangerousHostEnvVarName } from "./host-env-security-RnaFYKhk.js"; //#region src/agents/mcp-config-shared.ts /** * Shared MCP config coercion helpers. * * MCP transport setup uses these functions to normalize loose JSON config into * string records/arrays while dropping unsafe host environment variables. */ const MCP_EXPLICIT_CREDENTIAL_ENV_KEYS = new Set([ "AMQP_URL", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SECURITY_TOKEN", "AWS_SESSION_TOKEN", "AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "DATABASE_URL", "GH_TOKEN", "GITHUB_TOKEN", "GITLAB_TOKEN", "MONGODB_URI", "NODE_AUTH_TOKEN", "NPM_TOKEN", "REDIS_URL" ]); function isDangerousMcpStdioEnvVarName(rawKey) { if (isDangerousHostEnvVarName(rawKey)) return true; const key = normalizeEnvVarKey(rawKey); if (!key || MCP_EXPLICIT_CREDENTIAL_ENV_KEYS.has(key.toUpperCase())) return false; return isDangerousHostInheritedEnvVarName(key); } /** Returns whether a value is a plain MCP config record. */ function isMcpConfigRecord(value) { return value !== null && typeof value === "object" && !Array.isArray(value); } function toMcpFilteredStringRecord(value, options) { if (!isMcpConfigRecord(value)) return; let droppedByKey = false; const entries = Object.entries(value).map(([key, entry]) => { if (options?.shouldDropKey?.(key)) { droppedByKey = true; options?.onDroppedEntry?.(key, entry); return null; } if (typeof entry === "string") return [key, entry]; if (typeof entry === "number" || typeof entry === "boolean") return [key, String(entry)]; options?.onDroppedEntry?.(key, entry); return null; }).filter((entry) => entry !== null); if (entries.length === 0 && droppedByKey && options?.preserveEmptyWhenKeysDropped) return {}; return entries.length > 0 ? Object.fromEntries(entries) : void 0; } /** Coerces string/number/boolean entries from a config object into strings. */ function toMcpStringRecord(value, options) { return toMcpFilteredStringRecord(value, options); } /** Coerces MCP env config while dropping dangerous inherited host env names. */ function toMcpEnvRecord(value, options) { return toMcpFilteredStringRecord(value, { ...options, preserveEmptyWhenKeysDropped: true, shouldDropKey: (key) => isDangerousMcpStdioEnvVarName(key) }); } /** Coerces an MCP string-array config value, dropping non-string entries. */ function toMcpStringArray(value) { if (!Array.isArray(value)) return; const entries = value.filter((entry) => typeof entry === "string"); return entries.length > 0 ? entries : []; } //#endregion //#region src/agents/mcp-stdio.ts /** * Stdio MCP launch config normalization. * Accepts OpenClaw and upstream MCP config field names, keeping only * command/args/env/cwd needed to spawn a stdio server. */ /** Resolve raw MCP server config into a stdio launch config. */ function resolveStdioMcpServerLaunchConfig(raw, options) { if (!isMcpConfigRecord(raw)) return { ok: false, reason: "server config must be an object" }; if (typeof raw.command !== "string" || raw.command.trim().length === 0) { if (typeof raw.url === "string" && raw.url.trim().length > 0) return { ok: false, reason: "not a stdio server (has url)" }; return { ok: false, reason: "its command is missing" }; } const cwd = typeof raw.cwd === "string" && raw.cwd.trim().length > 0 ? raw.cwd : typeof raw.workingDirectory === "string" && raw.workingDirectory.trim().length > 0 ? raw.workingDirectory : void 0; return { ok: true, config: { command: raw.command, args: toMcpStringArray(raw.args), env: toMcpEnvRecord(raw.env, { onDroppedEntry: options?.onDroppedEnv }), cwd } }; } /** Describe a stdio MCP launch config for diagnostics. */ function describeStdioMcpServerLaunchConfig(config) { const args = Array.isArray(config.args) && config.args.length > 0 ? ` ${config.args.join(" ")}` : ""; const cwd = config.cwd ? ` (cwd=${config.cwd})` : ""; return `${config.command}${args}${cwd}`; } //#endregion export { toMcpStringRecord as i, resolveStdioMcpServerLaunchConfig as n, isMcpConfigRecord as r, describeStdioMcpServerLaunchConfig as t };