{"version":3,"file":"agentPluginMcp.mjs","names":[],"sources":["../src/services/agentPluginMcp/index.ts"],"sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport { validateHeaderName, validateHeaderValue } from 'node:http';\nimport { isIP } from 'node:net';\nimport path from 'node:path';\n\nimport {\n  AGENT_PLUGIN_MCP_SCHEMA_URL,\n  type DoomMcpAgentPluginProjectionSource,\n} from '@agimon-ai/doompi-core/mcpProjection';\n\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst RESERVED_ENVIRONMENT_KEYS = new Set(['PLUGIN_ROOT', 'PLUGIN_DATA']);\nconst PROXY_SERVER_ALIASES = new Set(['mcp-proxy', 'agiflow-proxy']);\n\ntype JsonObject = Record<string, unknown>;\n\nexport interface AgentPluginMcpConfigSource {\n  path: string;\n  format: 'internal';\n  cacheKey: string;\n}\n\nexport interface NormalizedAgentPluginMcpSource {\n  /** Owner-only, content-addressed layer that bypasses Claude env interpolation. */\n  configSource?: AgentPluginMcpConfigSource;\n  /** Claude-compatible definitions for an external merged config. */\n  claudeConfig: { mcpServers: Record<string, JsonObject> };\n  serverNames: string[];\n  droppedServers: string[];\n  diagnostics: string[];\n}\n\nexport interface NormalizeAgentPluginMcpOptions {\n  stagingDirectory: string;\n  /** Empty and absent lists both mean keep every server. */\n  allowedServers?: readonly string[];\n  /** Doom strips nested wrappers; external-only callers may opt out. */\n  stripProxyWrappers?: boolean;\n}\n\ninterface NormalizedServer {\n  internal: JsonObject;\n  claude: JsonObject;\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction onlyKeys(value: JsonObject, allowed: readonly string[], label: string): void {\n  const unexpected = Object.keys(value).find((key) => !allowed.includes(key));\n  if (unexpected) throw new Error(`${label} contains unsupported field \"${unexpected}\"`);\n}\n\nfunction nonEmptyString(value: unknown, label: string): string {\n  if (typeof value !== 'string' || value.length === 0) throw new Error(`${label} must be a non-empty string`);\n  return value;\n}\n\nfunction optionalStringArray(value: unknown, label: string): string[] | undefined {\n  if (value === undefined) return undefined;\n  if (!Array.isArray(value)) throw new Error(`${label} must be an array of strings`);\n  return value.map((item, index) => {\n    if (typeof item !== 'string') throw new Error(`${label}[${index}] must be a string`);\n    return item;\n  });\n}\n\nfunction optionalStringRecord(value: unknown, label: string): Record<string, string> | undefined {\n  if (value === undefined) return undefined;\n  if (!isObject(value)) throw new Error(`${label} must be an object of string values`);\n  return Object.fromEntries(\n    Object.entries(value).map(([key, item]) => {\n      if (typeof item !== 'string') throw new Error(`${label}.${key} must be a string`);\n      return [key, item];\n    }),\n  );\n}\n\nfunction expandPluginPlaceholders(value: string, pluginRoot: string, pluginDataDirectory: string): string {\n  // The portable contract is a single, non-recursive replacement pass. An\n  // unrecognised placeholder remains literal and mcp-proxy must not reinterpret it.\n  return value.replace(/\\$\\{PLUGIN_(ROOT|DATA)\\}/gu, (placeholder) =>\n    placeholder === '${PLUGIN_ROOT}' ? pluginRoot : pluginDataDirectory,\n  );\n}\n\nfunction isInside(root: string, candidate: string): boolean {\n  const relative = path.relative(root, candidate);\n  return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));\n}\n\nfunction realContainedPath(root: string, candidate: string, label: string): string {\n  let realCandidate: string;\n  try {\n    realCandidate = fs.realpathSync(candidate);\n  } catch {\n    throw new Error(`${label} does not exist`);\n  }\n  if (!isInside(root, realCandidate)) throw new Error(`${label} escapes its allowed plugin directory`);\n  return realCandidate;\n}\n\nfunction normalizeCommand(command: string, pluginRoot: string): string {\n  if (command.startsWith('./')) {\n    const resolved = realContainedPath(pluginRoot, path.resolve(pluginRoot, command), 'command');\n    if (!fs.statSync(resolved).isFile()) throw new Error('command must resolve to a regular file');\n    try {\n      fs.accessSync(resolved, fs.constants.X_OK);\n    } catch {\n      throw new Error('command must resolve to an executable file');\n    }\n    return resolved;\n  }\n  if (command === '.' || command === '..' || /[\\s/\\\\]/u.test(command)) {\n    throw new Error('command must be a bare executable name or a ./ path inside the plugin');\n  }\n  return command;\n}\n\nfunction normalizeWorkingDirectory(declared: unknown, pluginRoot: string, pluginDataDirectory: string): string {\n  if (declared === undefined) return pluginRoot;\n  const cwd = nonEmptyString(declared, 'cwd');\n  let base: string;\n  let expanded: string;\n  if (cwd.startsWith('./')) {\n    base = pluginRoot;\n    expanded = path.resolve(pluginRoot, cwd);\n  } else if (cwd === '${PLUGIN_ROOT}' || cwd.startsWith('${PLUGIN_ROOT}/')) {\n    base = pluginRoot;\n    expanded = expandPluginPlaceholders(cwd, pluginRoot, pluginDataDirectory);\n  } else if (cwd === '${PLUGIN_DATA}' || cwd.startsWith('${PLUGIN_DATA}/')) {\n    base = pluginDataDirectory;\n    expanded = expandPluginPlaceholders(cwd, pluginRoot, pluginDataDirectory);\n  } else {\n    throw new Error('cwd must start with ./, ${PLUGIN_ROOT}, or ${PLUGIN_DATA}');\n  }\n  const resolved = realContainedPath(base, path.resolve(expanded), 'cwd');\n  if (!fs.statSync(resolved).isDirectory()) throw new Error('cwd must resolve to a directory');\n  return resolved;\n}\n\nfunction normalizeEnvironment(value: unknown, pluginRoot: string, pluginDataDirectory: string): Record<string, string> {\n  const declared = optionalStringRecord(value, 'env') ?? {};\n  for (const key of Object.keys(declared)) {\n    const reservedKey = process.platform === 'win32' ? key.toUpperCase() : key;\n    if (RESERVED_ENVIRONMENT_KEYS.has(reservedKey)) {\n      throw new Error(`env key \"${key}\" is reserved by Agent Plugins`);\n    }\n  }\n  return {\n    ...Object.fromEntries(\n      Object.entries(declared).map(([key, item]) => [\n        key,\n        expandPluginPlaceholders(item, pluginRoot, pluginDataDirectory),\n      ]),\n    ),\n    PLUGIN_ROOT: pluginRoot,\n    PLUGIN_DATA: pluginDataDirectory,\n  };\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n  const bareHostname = hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n  if (bareHostname.toLowerCase() === 'localhost') return true;\n  const family = isIP(bareHostname);\n  if (family === 4) return bareHostname.split('.')[0] === '127';\n  return family === 6 && bareHostname === '::1';\n}\n\nfunction normalizeUrl(value: unknown): string {\n  const raw = nonEmptyString(value, 'url');\n  let parsed: URL;\n  try {\n    parsed = new URL(raw);\n  } catch {\n    throw new Error('url must be an absolute HTTP(S) URL');\n  }\n  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n    throw new Error('url must use http or https');\n  }\n  if (parsed.username || parsed.password) throw new Error('url must not contain user information');\n  if (parsed.hash) throw new Error('url must not contain a fragment');\n  if (parsed.protocol === 'http:' && !isLoopbackHost(parsed.hostname)) {\n    throw new Error('non-loopback MCP URLs must use https');\n  }\n  return raw;\n}\n\nfunction normalizeHeaders(value: unknown): Record<string, string> | undefined {\n  const headers = optionalStringRecord(value, 'headers');\n  if (!headers) return undefined;\n  const seen = new Set<string>();\n  for (const [name, item] of Object.entries(headers)) {\n    const canonical = name.toLowerCase();\n    if (seen.has(canonical)) throw new Error(`headers contain duplicate name \"${name}\"`);\n    seen.add(canonical);\n    try {\n      validateHeaderName(name);\n      validateHeaderValue(name, item);\n    } catch {\n      throw new Error(`header \"${name}\" is invalid`);\n    }\n  }\n  return headers;\n}\n\nfunction normalizeServer(\n  raw: unknown,\n  pluginRoot: string,\n  pluginDataDirectory: string,\n  name: string,\n): NormalizedServer {\n  if (!isObject(raw)) throw new Error('definition must be an object');\n  const type = nonEmptyString(raw.type, 'type');\n  if (type === 'stdio') {\n    onlyKeys(raw, ['type', 'command', 'args', 'env', 'cwd'], `server \"${name}\"`);\n    const command = normalizeCommand(nonEmptyString(raw.command, 'command'), pluginRoot);\n    const args = optionalStringArray(raw.args, 'args')?.map((item) =>\n      expandPluginPlaceholders(item, pluginRoot, pluginDataDirectory),\n    );\n    const env = normalizeEnvironment(raw.env, pluginRoot, pluginDataDirectory);\n    const cwd = normalizeWorkingDirectory(raw.cwd, pluginRoot, pluginDataDirectory);\n    const config = { command, ...(args ? { args } : {}), env, cwd };\n    return {\n      internal: { name, transport: 'stdio', config },\n      claude: { type: 'stdio', ...config },\n    };\n  }\n\n  if (type === 'streamable-http' || type === 'sse') {\n    onlyKeys(raw, ['type', 'url', 'headers'], `server \"${name}\"`);\n    const url = normalizeUrl(raw.url);\n    const headers = normalizeHeaders(raw.headers);\n    const transport = type === 'streamable-http' ? 'http' : 'sse';\n    const config = { url, ...(headers ? { headers } : {}) };\n    return {\n      internal: { name, transport, config },\n      claude: { type: transport, ...config },\n    };\n  }\n\n  throw new Error(`unsupported transport type \"${type}\"`);\n}\n\nfunction stagedInternalPath(\n  source: DoomMcpAgentPluginProjectionSource,\n  contents: string,\n  stagingDirectory: string,\n): string {\n  const digest = createHash('sha256')\n    .update(source.sourceId)\n    .update('\\0')\n    .update(source.contentDigest)\n    .update('\\0')\n    .update(contents)\n    .digest('hex')\n    .slice(0, 20);\n  return path.join(stagingDirectory, `agent-plugin-mcp-${digest}.internal.json`);\n}\n\nfunction writeStagedInternalConfig(target: string, contents: string, stagingDirectory: string): void {\n  fs.mkdirSync(stagingDirectory, { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n  fs.chmodSync(stagingDirectory, PRIVATE_DIRECTORY_MODE);\n  const temporaryPath = `${target}.${process.pid}-${randomUUID()}.tmp`;\n  try {\n    fs.writeFileSync(temporaryPath, contents, { flag: 'wx', mode: PRIVATE_FILE_MODE });\n    try {\n      fs.renameSync(temporaryPath, target);\n    } catch (error) {\n      const code = (error as NodeJS.ErrnoException).code;\n      if (code !== 'EEXIST' && code !== 'EPERM') throw error;\n      const stat = fs.lstatSync(target);\n      if (stat.isSymbolicLink() || !stat.isFile() || fs.readFileSync(target, 'utf8') !== contents) {\n        throw new Error('content-addressed staging path is occupied by different content');\n      }\n    }\n    fs.chmodSync(target, PRIVATE_FILE_MODE);\n  } finally {\n    fs.rmSync(temporaryPath, { force: true });\n  }\n}\n\nfunction emptyResult(diagnostic: string): NormalizedAgentPluginMcpSource {\n  return {\n    claudeConfig: { mcpServers: {} },\n    serverNames: [],\n    droppedServers: [],\n    diagnostics: [diagnostic],\n  };\n}\n\n/**\n * Validates one Agent Plugins v1 `mcp.json` and stages a native mcp-proxy layer.\n *\n * Server validation is isolated: one malformed server is diagnosed and skipped.\n * Document/schema, source identity, or plugin-boundary failures reject the whole\n * source. Only the two portable plugin placeholders are expanded; the staged\n * layer is tagged `internal`, so legacy `${ENV}` interpolation cannot run again.\n */\nexport function normalizeAgentPluginMcpSource(\n  source: DoomMcpAgentPluginProjectionSource,\n  options: NormalizeAgentPluginMcpOptions,\n): NormalizedAgentPluginMcpSource {\n  const label = `Agent Plugin MCP source \"${source.sourceId}\"`;\n  try {\n    if (source.mcpSchemaUrl !== AGENT_PLUGIN_MCP_SCHEMA_URL) {\n      throw new Error(`unsupported schema \"${String(source.mcpSchemaUrl)}\"`);\n    }\n    if (!path.isAbsolute(source.pluginRoot) || !path.isAbsolute(source.pluginDataDirectory)) {\n      throw new Error('pluginRoot and pluginDataDirectory must be absolute');\n    }\n    const pluginRoot = fs.realpathSync(source.pluginRoot);\n    try {\n      const dataStat = fs.lstatSync(source.pluginDataDirectory);\n      if (dataStat.isSymbolicLink() || !dataStat.isDirectory()) {\n        throw new Error('pluginDataDirectory must be a real directory');\n      }\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n      fs.mkdirSync(source.pluginDataDirectory, { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n    }\n    fs.chmodSync(source.pluginDataDirectory, PRIVATE_DIRECTORY_MODE);\n    fs.accessSync(source.pluginDataDirectory, fs.constants.W_OK);\n    const pluginDataDirectory = fs.realpathSync(source.pluginDataDirectory);\n    const configPath = realContainedPath(pluginRoot, source.configPath, 'mcp.json');\n    if (path.dirname(configPath) !== pluginRoot || path.basename(configPath) !== 'mcp.json') {\n      throw new Error('portable plugin config must be root mcp.json');\n    }\n\n    const bytes = fs.readFileSync(configPath);\n    const digest = createHash('sha256').update(bytes).digest('hex');\n    if (digest !== source.contentDigest) throw new Error('content digest does not match the projection');\n    const parsed: unknown = JSON.parse(bytes.toString('utf8'));\n    if (!isObject(parsed)) throw new Error('document must be an object');\n    onlyKeys(parsed, ['$schema', 'mcpServers'], label);\n    if (parsed.$schema !== source.mcpSchemaUrl) throw new Error('$schema does not match the projected schema');\n    if (!isObject(parsed.mcpServers)) throw new Error('mcpServers must be an object');\n\n    const allowed = options.allowedServers;\n    const keepAll = !allowed || allowed.length === 0;\n    const stripProxyWrappers = options.stripProxyWrappers ?? true;\n    const internalServers = Object.create(null) as Record<string, JsonObject>;\n    const claudeServers = Object.create(null) as Record<string, JsonObject>;\n    const droppedServers: string[] = [];\n    const diagnostics: string[] = [];\n\n    for (const [name, rawServer] of Object.entries(parsed.mcpServers)) {\n      if (!name) {\n        diagnostics.push(`${label} contains an empty server name; that entry was skipped.`);\n        continue;\n      }\n      if ((!keepAll && !allowed.includes(name)) || (stripProxyWrappers && PROXY_SERVER_ALIASES.has(name))) {\n        droppedServers.push(name);\n        continue;\n      }\n      try {\n        const normalized = normalizeServer(rawServer, pluginRoot, pluginDataDirectory, name);\n        internalServers[name] = normalized.internal;\n        claudeServers[name] = normalized.claude;\n      } catch (error) {\n        droppedServers.push(name);\n        diagnostics.push(\n          `${label} skipped server \"${name}\": ${error instanceof Error ? error.message : String(error)}`,\n        );\n      }\n    }\n\n    const internalConfig = { mcpServers: internalServers };\n    const contents = `${JSON.stringify(internalConfig, null, 2)}\\n`;\n    const target = stagedInternalPath(source, contents, options.stagingDirectory);\n    writeStagedInternalConfig(target, contents, options.stagingDirectory);\n    const cacheKey = createHash('sha256')\n      .update('agent-plugin-v1\\0')\n      .update(source.sourceId)\n      .update('\\0')\n      .update(source.contentDigest)\n      .update('\\0')\n      .update(configPath)\n      .update('\\0')\n      .update(contents)\n      .digest('hex');\n\n    return {\n      configSource: { path: target, format: 'internal', cacheKey },\n      claudeConfig: { mcpServers: claudeServers },\n      serverNames: Object.keys(internalServers),\n      droppedServers,\n      diagnostics,\n    };\n  } catch (error) {\n    return emptyResult(`${label} was disabled: ${error instanceof Error ? error.message : String(error)}`);\n  }\n}\n"],"mappings":"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"}