@schoolai/shipyard 3.14.0 → 3.15.0

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.
Files changed (37) hide show
  1. package/dist/capability-detector-worker.js +5 -5
  2. package/dist/{chunk-OX3UY44R.js → chunk-5PBWS7BB.js} +31 -42
  3. package/dist/chunk-5PBWS7BB.js.map +1 -0
  4. package/dist/{chunk-RCEAMZVG.js → chunk-6SK6FBYC.js} +2 -2
  5. package/dist/{chunk-M3WBYTB3.js → chunk-AXHG3QQA.js} +16 -1
  6. package/dist/chunk-AXHG3QQA.js.map +1 -0
  7. package/dist/{chunk-T3OTZ66B.js → chunk-B7WZUKYX.js} +219 -86
  8. package/dist/chunk-B7WZUKYX.js.map +1 -0
  9. package/dist/{chunk-BUAEJNUG.js → chunk-HPDRJ4VZ.js} +3 -3
  10. package/dist/{chunk-BUAEJNUG.js.map → chunk-HPDRJ4VZ.js.map} +1 -1
  11. package/dist/{chunk-WGS7ZW6N.js → chunk-L5FQEZ6Y.js} +3 -3
  12. package/dist/{chunk-KUPHN3ZN.js → chunk-RHHRJR3L.js} +2 -2
  13. package/dist/{chunk-3KE2VDKA.js → chunk-VKY7UXTP.js} +25 -3
  14. package/dist/chunk-VKY7UXTP.js.map +1 -0
  15. package/dist/{chunk-IWBDVGD2.js → chunk-VTALUCDB.js} +2 -2
  16. package/dist/cursor-runner.js +3 -3
  17. package/dist/electron-utility.js +2 -2
  18. package/dist/index.js +4 -4
  19. package/dist/{login-HRR3T4SZ.js → login-EYGYOEXL.js} +3 -3
  20. package/dist/{mcp-servers-GUA5WOHO.js → mcp-servers-DSOX243C.js} +8 -2
  21. package/dist/{plan-backfill-QNJUWOYP.js → plan-backfill-SMJEKTMM.js} +4 -4
  22. package/dist/{serve-25I4ML7R.js → serve-DAP6V7SY.js} +339 -147
  23. package/dist/{serve-25I4ML7R.js.map → serve-DAP6V7SY.js.map} +1 -1
  24. package/dist/{start-O2DXLW23.js → start-AX2ZK3AY.js} +6 -6
  25. package/package.json +1 -1
  26. package/dist/chunk-3KE2VDKA.js.map +0 -1
  27. package/dist/chunk-M3WBYTB3.js.map +0 -1
  28. package/dist/chunk-OX3UY44R.js.map +0 -1
  29. package/dist/chunk-T3OTZ66B.js.map +0 -1
  30. /package/dist/{chunk-RCEAMZVG.js.map → chunk-6SK6FBYC.js.map} +0 -0
  31. /package/dist/{chunk-WGS7ZW6N.js.map → chunk-L5FQEZ6Y.js.map} +0 -0
  32. /package/dist/{chunk-KUPHN3ZN.js.map → chunk-RHHRJR3L.js.map} +0 -0
  33. /package/dist/{chunk-IWBDVGD2.js.map → chunk-VTALUCDB.js.map} +0 -0
  34. /package/dist/{login-HRR3T4SZ.js.map → login-EYGYOEXL.js.map} +0 -0
  35. /package/dist/{mcp-servers-GUA5WOHO.js.map → mcp-servers-DSOX243C.js.map} +0 -0
  36. /package/dist/{plan-backfill-QNJUWOYP.js.map → plan-backfill-SMJEKTMM.js.map} +0 -0
  37. /package/dist/{start-O2DXLW23.js.map → start-AX2ZK3AY.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/capabilities/mcp-servers.ts","../src/shared/mcp/claude-code-credentials.ts","../src/shared/mcp/schemas.ts","../src/shared/mcp/resolve-servers.ts","../src/shared/mcp/token-store.ts","../src/shared/auth/anthropic-credentials.ts","../src/shared/capabilities/runtime/catalog.ts","../src/shared/capabilities/account-integrations.ts"],"sourcesContent":["import { readFile, stat } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { basename, join, resolve } from 'node:path';\nimport type { AnthropicAuthMethod } from '@shipyard/loro-schema';\nimport type { GitRepoInfo, MCPServerInfo, MCPServerSource } from '@shipyard/session';\nimport { parse as parseToml } from 'toml';\nimport { z } from 'zod';\nimport { logger } from '../logger.js';\nimport { readClaudeCodeCredentials } from '../mcp/claude-code-credentials.js';\nimport { VAULT_REF_PATTERN } from '../mcp/resolve-servers.js';\nimport { selectTokenByUrl } from '../mcp/token-store.js';\nimport { fetchClaudeAiIntegrations } from './account-integrations.js';\nimport { CLAUDE_CODE_RUNTIME_ID, getRuntimeDisplayName } from './runtime/catalog.js';\n\nconst MCPStdioEntrySchema = z\n .object({\n type: z.literal('stdio').optional(),\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n enabled: z.boolean().optional(),\n })\n .passthrough();\n\nconst MCPOAuthConfigSchema = z\n .object({\n clientId: z.string().optional(),\n callbackPort: z.number().optional(),\n })\n .passthrough();\n\nconst MCPHttpEntrySchema = z\n .object({\n type: z.literal('http'),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n oauth: MCPOAuthConfigSchema.optional(),\n enabled: z.boolean().optional(),\n })\n .passthrough();\n\nconst MCPSSEEntrySchema = z\n .object({\n type: z.literal('sse'),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n enabled: z.boolean().optional(),\n })\n .passthrough();\n\nconst MCPServerEntrySchema = z.union([MCPStdioEntrySchema, MCPHttpEntrySchema, MCPSSEEntrySchema]);\nconst CodexEnvVarSchema = z.union([\n z.string(),\n z\n .object({\n name: z.string(),\n source: z.string().optional(),\n })\n .passthrough(),\n]);\nconst CodexMCPStdioEntrySchema = z\n .object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n env_vars: z.array(CodexEnvVarSchema).optional(),\n enabled: z.boolean().optional(),\n })\n .passthrough();\nconst CodexMCPHttpEntrySchema = z\n .object({\n url: z.string(),\n http_headers: z.record(z.string(), z.string()).optional(),\n env_http_headers: z.record(z.string(), z.string()).optional(),\n bearer_token_env_var: z.string().optional(),\n enabled: z.boolean().optional(),\n })\n .passthrough();\n\n/**\n * Pure decision: should `fetchClaudeAiIntegrations` (the claude.ai Connectors\n * fetch) actually run for this user?\n *\n * Only the claude.ai OAuth method has access to that endpoint. `null` or\n * `undefined` (preference unknown — pre-backfill or caller didn't plumb the\n * value through) returns true to preserve the legacy behaviour for OAuth\n * users during the rollout window before the boot backfill writes a real\n * value. After backfill, `null` should be vanishingly rare.\n */\nexport function shouldFetchClaudeAiIntegrations(\n preferredAuth: AnthropicAuthMethod | null | undefined\n): boolean {\n if (preferredAuth == null) return true;\n return preferredAuth === 'claude-ai';\n}\n\n/**\n * Pure: derive a stable dedup key for an MCP server.\n *\n * The same cloud connector is registered under different display-name casings\n * depending on its source — claude.ai uses `Notion` (source: claudeai) while\n * ~/.mcp.json uses `notion` (source: user). Deduplication keyed on the exact\n * `server.name` string lets both survive as separate entries, doubling the\n * per-task disabled/snapshot lists and causing double-authentication prompts.\n *\n * The canonical identity for URL-based servers is the URL (matching the\n * token-store's `selectTokenByUrl` cross-source lookup). For stdio servers\n * there is no URL, so we fall back to the lowercased name.\n *\n * Normalization: lowercase scheme+host, strip one trailing `/` from the end.\n * Path/query are preserved as-is because two servers at the same host but\n * different paths ARE distinct.\n */\nexport function canonicalMcpServerKey(server: { name: string; url?: string }): string {\n if (!server.url) return server.name.toLowerCase();\n try {\n const parsed = new URL(server.url);\n parsed.hostname = parsed.hostname.toLowerCase();\n parsed.protocol = parsed.protocol.toLowerCase();\n const normalized = parsed.toString();\n return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;\n } catch {\n // NOTE: malformed url → fall back to the name so dedup never throws.\n return server.name.toLowerCase();\n }\n}\n\n/**\n * Pure: collapse a flat list of server candidates into one entry per canonical\n * identity. Higher-priority candidate wins (>= keeps the later-seen winner when\n * priorities tie). `runtimeId` is retained on candidates as source metadata;\n * it no longer filters visibility because Shipyard pushes the enabled MCP set\n * to every agent profile.\n *\n * After dedup, each surviving entry gets:\n * - `sources`: de-duplicated ordered set of all discovery sources across\n * collapsed candidates (preserves first-seen order, removes duplicates).\n * - `id`: carried from any collapsed candidate that has a non-empty `id`\n * (the `mcpsrv_` gateway id lives only on the `claudeai` candidate, which\n * may lose the priority race to a higher-priority local entry).\n *\n * Extracted from `detectMCPServersInner` so it can be unit-tested directly.\n */\nexport function dedupeServerCandidates(candidates: DetectedServerCandidate[]): MCPServerInfo[] {\n const deduped = new Map<string, DetectedServerCandidate>();\n /**\n * Accumulate sources + ids across ALL candidates sharing a canonical key,\n * regardless of which one wins on priority. Indexed in insertion order so\n * the first-seen source appears first in the output array.\n */\n const allSources = new Map<string, MCPServerSource[]>();\n const firstId = new Map<string, string>();\n\n for (const candidate of candidates) {\n const key = canonicalMcpServerKey(candidate.server);\n const existing = deduped.get(key);\n if (!existing || candidate.priority >= existing.priority) {\n deduped.set(key, candidate);\n }\n\n const src = candidate.server.source;\n const srcs = allSources.get(key);\n if (srcs === undefined) {\n allSources.set(key, [src]);\n } else if (!srcs.includes(src)) {\n srcs.push(src);\n }\n\n if (!firstId.has(key) && candidate.server.id) {\n firstId.set(key, candidate.server.id);\n }\n }\n\n return [...deduped.values()].map((candidate) => {\n const key = canonicalMcpServerKey(candidate.server);\n const sources = allSources.get(key) ?? [candidate.server.source];\n const id = firstId.get(key) ?? candidate.server.id;\n return {\n ...candidate.server,\n sources,\n ...(id !== undefined ? { id } : {}),\n };\n });\n}\n\nconst SECRET_PATTERNS = /^(sk-|ghp_|gho_|glpat-|xoxb-|xoxp-|Bearer\\s|token\\s)/i;\nconst SECRET_FLAGS = new Set(['--api-key', '--token', '--secret', '--password', '--key', '-k']);\n\nexport function redactArgs(args: string[]): string[] {\n return args.map((arg, i) => {\n if (SECRET_PATTERNS.test(arg)) return '***';\n const prevArg = i > 0 ? args[i - 1] : undefined;\n if (prevArg && SECRET_FLAGS.has(prevArg)) return '***';\n const eqIdx = arg.indexOf('=');\n if (eqIdx > 0 && SECRET_FLAGS.has(arg.slice(0, eqIdx))) {\n return `${arg.slice(0, eqIdx + 1)}***`;\n }\n return arg;\n });\n}\n\n/**\n * Redact all environment variable values. Env vars passed to MCP servers\n * frequently contain secrets (API keys, tokens) and should never be\n * exposed to the browser.\n */\nexport function redactEnv(env: Record<string, string>): Record<string, string> {\n const result: Record<string, string> = {};\n for (const key of Object.keys(env)) {\n result[key] = '***';\n }\n return result;\n}\n\ntype MCPStdioEntry = z.infer<typeof MCPStdioEntrySchema>;\ntype MCPHttpEntry = z.infer<typeof MCPHttpEntrySchema>;\ntype MCPSSEEntry = z.infer<typeof MCPSSEEntrySchema>;\ntype CodexMCPStdioEntry = z.infer<typeof CodexMCPStdioEntrySchema>;\ntype CodexMCPHttpEntry = z.infer<typeof CodexMCPHttpEntrySchema>;\ntype MCPSourceMetadata = Pick<MCPServerInfo, 'runtimeId' | 'sourceLabel' | 'sourcePath'>;\ninterface ParsedConfigResult {\n servers: MCPServerInfo[];\n invalid: InvalidEntry[];\n}\ninterface DetectedServerCandidate {\n server: MCPServerInfo;\n priority: number;\n}\n\nfunction isHttpEntry(data: MCPStdioEntry | MCPHttpEntry | MCPSSEEntry): data is MCPHttpEntry {\n return 'type' in data && data.type === 'http';\n}\n\nfunction isSSEEntry(data: MCPStdioEntry | MCPHttpEntry | MCPSSEEntry): data is MCPSSEEntry {\n return 'type' in data && data.type === 'sse';\n}\n\nfunction entryToServerInfo(\n name: string,\n data: MCPStdioEntry | MCPHttpEntry | MCPSSEEntry,\n source: MCPServerSource,\n metadata: MCPSourceMetadata = {}\n): MCPServerInfo {\n if (isHttpEntry(data)) {\n return {\n name,\n type: 'http',\n runtimeId: metadata.runtimeId,\n url: data.url,\n headers: data.headers,\n oauth: data.oauth,\n enabled: data.enabled ?? true,\n source,\n sourceLabel: metadata.sourceLabel,\n sourcePath: metadata.sourcePath,\n authStatus: 'unknown' as const,\n };\n }\n if (isSSEEntry(data)) {\n return {\n name,\n type: 'sse',\n runtimeId: metadata.runtimeId,\n url: data.url,\n headers: data.headers,\n enabled: data.enabled ?? true,\n source,\n sourceLabel: metadata.sourceLabel,\n sourcePath: metadata.sourcePath,\n authStatus: 'unknown' as const,\n };\n }\n return {\n name,\n type: 'stdio',\n runtimeId: metadata.runtimeId,\n command: data.command,\n args: data.args,\n env: data.env,\n enabled: data.enabled ?? true,\n source,\n sourceLabel: metadata.sourceLabel,\n sourcePath: metadata.sourcePath,\n authStatus: 'unknown' as const,\n };\n}\n\nfunction codexEnvVarsToPlaceholders(\n envVars: CodexMCPStdioEntry['env_vars']\n): Record<string, string> | undefined {\n if (!envVars || envVars.length === 0) return undefined;\n const result: Record<string, string> = {};\n for (const envVar of envVars) {\n const name = typeof envVar === 'string' ? envVar : envVar.name;\n result[name] = `\\${${name}}`;\n }\n return result;\n}\n\nfunction codexHttpHeadersToPlaceholders(\n envHeaders: CodexMCPHttpEntry['env_http_headers']\n): Record<string, string> | undefined {\n if (!envHeaders) return undefined;\n const result: Record<string, string> = {};\n for (const [header, envVar] of Object.entries(envHeaders)) {\n result[header] = `\\${${envVar}}`;\n }\n return result;\n}\n\nfunction codexEntryToServerInfo(\n name: string,\n data: CodexMCPStdioEntry | CodexMCPHttpEntry,\n source: MCPServerSource,\n metadata: MCPSourceMetadata\n): MCPServerInfo {\n if (isCodexStdioEntry(data)) {\n return {\n name,\n type: 'stdio',\n runtimeId: metadata.runtimeId,\n command: data.command,\n args: data.args,\n env: {\n ...(data.env ?? {}),\n ...(codexEnvVarsToPlaceholders(data.env_vars) ?? {}),\n },\n enabled: data.enabled ?? true,\n source,\n sourceLabel: metadata.sourceLabel,\n sourcePath: metadata.sourcePath,\n authStatus: 'unknown' as const,\n };\n }\n\n const headers = {\n ...(data.http_headers ?? {}),\n ...(codexHttpHeadersToPlaceholders(data.env_http_headers) ?? {}),\n };\n if (data.bearer_token_env_var) {\n headers.Authorization = `Bearer \\${${data.bearer_token_env_var}}`;\n }\n\n return {\n name,\n type: 'http',\n runtimeId: metadata.runtimeId,\n url: data.url,\n headers,\n enabled: data.enabled ?? true,\n source,\n sourceLabel: metadata.sourceLabel,\n sourcePath: metadata.sourcePath,\n authStatus: 'unknown' as const,\n };\n}\n\nfunction isCodexStdioEntry(\n data: CodexMCPStdioEntry | CodexMCPHttpEntry\n): data is CodexMCPStdioEntry {\n return isObjectRecord(data) && typeof data.command === 'string';\n}\n\n/**\n * Callback the detectors use to surface structured log entries. The level\n * routing for it lives in `mcp-detection-log.ts` (`logMcpDetectionEntry`).\n */\nexport type Log = (entry: { event: string; [key: string]: unknown }) => void;\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseTomlRecord(raw: string): Record<string, unknown> {\n const parsed = parseToml(raw);\n return isObjectRecord(parsed) ? parsed : {};\n}\n\n/**\n * Path-aware: `settings.json` / `settings.local.json` only carry MCP servers\n * under the explicit `mcpServers` wrapper — their top-level keys are Claude\n * Code config (`hooks`, `permissions`, `env`, `statusLine`, `enabledPlugins`,\n * `spinnerVerbs`, ...) that will never validate as MCP entries. Falling\n * through to iterate them produced 100k+ `mcp_config_entry_invalid` warnings\n * per 15min in #3264. Other files (`.mcp.json`, `~/.claude.json`) keep the\n * fallthrough — `.mcp.json` puts servers at the top level by spec.\n *\n * #3293 follow-on: even with the path-aware fix, files that DO have an\n * `mcpServers` wrapper containing malformed entries (e.g. mis-keyed\n * `hooks`-style records pasted into `mcpServers`) still produced per-entry\n * warning events on every scan. With 80+ worktrees × multiple scans per\n * minute × 6-10 invalid entries per file, the daemon's event loop saturated\n * (29k warnings / 9min, worst freeze 5.8s).\n *\n * Two defenses now applied at this chokepoint:\n * 1. **mtime cache** — stat() the file first; skip the entire read+parse+\n * validate cycle when `stat.mtimeMs` matches the prior validation's\n * cached value. Stable malformed configs across many worktrees produce\n * ~99% cache hits per scan cycle.\n * 2. **Aggregated + throttled warnings** — invalid entries are accumulated\n * into a single `config_entry_invalid` event per file per scan (with\n * `invalidCount` and the first 3 error messages). The warn-level\n * emission is throttled to once per 60s per file; intermediate\n * re-validations log at `debug` level so the firestorm cannot recur but\n * debug-level observability is preserved. Bad entries are still\n * REJECTED — only the log shape changes.\n */\nconst WARN_THROTTLE_MS = 60_000;\n\ninterface ConfigCacheEntry {\n mtime: number;\n result: MCPServerInfo[];\n /**\n * Extra invalidation token beyond mtime, for readers whose result depends on\n * more than the file's mtime (e.g. the local-scope reader's active env set).\n * `undefined` for readers gated on mtime alone.\n */\n variant?: string;\n}\n\ninterface InvalidEntry {\n name: string;\n error: string;\n}\n\nconst validationCache = new Map<string, ConfigCacheEntry>();\nconst lastWarnAtByPath = new Map<string, number>();\n\n/**\n * Clear the in-process mtime cache + warn-throttle map. Test-only — production\n * relies on natural eviction via mtime change. Exported so unit tests can\n * isolate cases without resorting to module-reload tricks.\n */\nexport function resetMCPConfigCaches(): void {\n validationCache.clear();\n lastWarnAtByPath.clear();\n}\n\nfunction validateJsonEntries(\n entries: Record<string, unknown>,\n source: MCPServerSource,\n metadata: MCPSourceMetadata\n): ParsedConfigResult {\n const servers: MCPServerInfo[] = [];\n const invalid: InvalidEntry[] = [];\n for (const [name, value] of Object.entries(entries)) {\n if (name === 'mcpServers') continue;\n if (typeof value !== 'object' || value === null || Array.isArray(value)) continue;\n const result = MCPServerEntrySchema.safeParse(value);\n if (!result.success) {\n invalid.push({ name, error: result.error.message });\n continue;\n }\n servers.push(entryToServerInfo(name, result.data, source, metadata));\n }\n return { servers, invalid };\n}\n\nfunction validateCodexEntries(\n entries: Record<string, unknown>,\n source: MCPServerSource,\n metadata: MCPSourceMetadata\n): ParsedConfigResult {\n const servers: MCPServerInfo[] = [];\n const invalid: InvalidEntry[] = [];\n for (const [name, value] of Object.entries(entries)) {\n if (!isObjectRecord(value)) continue;\n const result =\n 'command' in value\n ? CodexMCPStdioEntrySchema.safeParse(value)\n : 'url' in value\n ? CodexMCPHttpEntrySchema.safeParse(value)\n : { success: false as const, error: { message: 'invalid transport' } };\n if (!result.success) {\n invalid.push({ name, error: result.error.message });\n continue;\n }\n servers.push(codexEntryToServerInfo(name, result.data, source, metadata));\n }\n return { servers, invalid };\n}\n\nfunction emitAggregateInvalid(\n filePath: string,\n source: MCPServerSource,\n invalid: InvalidEntry[],\n log: Log,\n now: number\n): void {\n const payload = {\n event: 'config_entry_invalid' as const,\n source,\n filePath,\n invalidCount: invalid.length,\n errors: invalid.slice(0, 3),\n };\n const last = lastWarnAtByPath.get(filePath) ?? 0;\n if (now - last >= WARN_THROTTLE_MS) {\n log(payload);\n lastWarnAtByPath.set(filePath, now);\n return;\n }\n /**\n * Within the per-file 60s throttle window — emit at debug level so the\n * firestorm cannot recur via the WARN-routed log adapter, but the event\n * is still observable for diagnostics with debug logging enabled.\n */\n logger.debug(payload, payload.event);\n}\n\nasync function readCachedMcpConfig(\n filePath: string,\n source: MCPServerSource,\n log: Log,\n parse: (raw: string) => ParsedConfigResult,\n /** Test seam: defaults to `Date.now`. */\n now: () => number = Date.now,\n /**\n * Cache key, defaults to `filePath`. Override when two readers parse the\n * SAME file into different server sets (e.g. `.claude.json`'s top-level\n * `mcpServers` vs its per-cwd `projects[cwd].mcpServers`) so they don't\n * collide on a shared key. The mtime stat/read still uses `filePath`.\n */\n cacheKey: string = filePath,\n /**\n * Extra invalidation token beyond mtime. Pass a STABLE `cacheKey` plus a\n * `cacheVariant` when the result depends on more than the file (e.g. the\n * active env set): the single entry is re-validated when the variant\n * changes instead of accumulating an orphan entry per distinct key.\n */\n cacheVariant?: string\n): Promise<MCPServerInfo[]> {\n let mtime: number;\n try {\n const st = await stat(filePath);\n mtime = st.mtimeMs;\n } catch {\n /**\n * File doesn't exist (or unreadable stat). Don't cache — a future scan\n * might race a file-create and we want to pick it up. Cheap fs call\n * with no read/parse/validate work, so unrolling the cache is fine.\n */\n return [];\n }\n\n const cached = validationCache.get(cacheKey);\n if (cached && cached.mtime === mtime && cached.variant === cacheVariant) {\n return cached.result;\n }\n\n let servers: MCPServerInfo[] = [];\n try {\n const raw = await readFile(filePath, 'utf-8');\n const parsed = parse(raw);\n servers = parsed.servers;\n if (parsed.invalid.length > 0) {\n emitAggregateInvalid(filePath, source, parsed.invalid, log, now());\n }\n } catch {\n /**\n * Read/parse failure — cache an empty result keyed on the failing\n * mtime so repeated scans don't keep re-reading the same broken file\n * until the user touches it. Mirrors the cache-on-success branch.\n */\n servers = [];\n }\n\n validationCache.set(cacheKey, { mtime, result: servers, variant: cacheVariant });\n return servers;\n}\n\nexport async function readMCPConfig(\n filePath: string,\n source: MCPServerSource,\n log: Log,\n metadataOrNow: MCPSourceMetadata | (() => number) = {},\n /** Test seam: defaults to `Date.now`. */\n now: () => number = Date.now\n): Promise<MCPServerInfo[]> {\n const metadata =\n typeof metadataOrNow === 'function' ? ({} satisfies MCPSourceMetadata) : metadataOrNow;\n const effectiveNow = typeof metadataOrNow === 'function' ? metadataOrNow : now;\n return readCachedMcpConfig(\n filePath,\n source,\n log,\n (raw) => {\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; validated per-entry below\n const json = JSON.parse(raw) as Record<string, unknown>;\n\n const fileName = basename(filePath);\n /**\n * Files whose MCP servers live ONLY under the `mcpServers` wrapper. When\n * the wrapper is absent, their top-level keys are app config, NOT MCP\n * servers — iterating them produced noise. `.claude.json` belongs here:\n * its top level is Claude.ai internal config (`tipsHistory`,\n * `cachedDynamicConfigs`, `cachedGrowthBookFeatures`, …) which spammed\n * `config_entry_invalid` every scan (Rudy's logs: 36/scan). `.mcp.json`\n * is the exception — it puts servers at the top level by spec.\n */\n const isWrapperOnlyFile =\n fileName === 'settings.json' ||\n fileName === 'settings.local.json' ||\n fileName === '.claude.json';\n\n let entries: Record<string, unknown> | null;\n if (isObjectRecord(json.mcpServers)) {\n entries = json.mcpServers;\n } else if (isWrapperOnlyFile) {\n entries = null;\n } else {\n entries = json;\n }\n\n return entries === null\n ? { servers: [], invalid: [] }\n : validateJsonEntries(entries, source, metadata);\n },\n effectiveNow\n );\n}\n\n/** Extract `projects[envPath].mcpServers` for each active env from a parsed `~/.claude.json`. */\nfunction parseClaudeJsonLocalEntries(\n json: Record<string, unknown>,\n envPaths: readonly string[],\n metadata: MCPSourceMetadata\n): ParsedConfigResult {\n const projects = isObjectRecord(json.projects) ? json.projects : null;\n if (!projects) return { servers: [], invalid: [] };\n const servers: MCPServerInfo[] = [];\n const invalid: InvalidEntry[] = [];\n for (const envPath of envPaths) {\n const project = projects[envPath];\n if (!isObjectRecord(project)) continue;\n const projectMcpServers = project.mcpServers;\n if (!isObjectRecord(projectMcpServers)) continue;\n const parsed = validateJsonEntries(projectMcpServers, 'local', metadata);\n servers.push(...parsed.servers);\n invalid.push(...parsed.invalid);\n }\n return { servers, invalid };\n}\n\n/**\n * Read Claude Code's `local` MCP scope from `~/.claude.json`.\n *\n * `claude mcp add` defaults to `local` scope, which is stored under\n * `projects[<cwd>].mcpServers` — NOT at the top level (that's `user` scope,\n * read by `readMCPConfig`) and NOT in `.mcp.json` (that's `project` scope).\n * Because `readMCPConfig` treats `.claude.json` as wrapper-only and reads only\n * the top-level `mcpServers`, local-scope servers were silently dropped for\n * every agent. This reader extracts `projects[envPath].mcpServers` for each\n * active environment, surfacing them exactly as Claude Code would for that cwd.\n *\n * The caller tags these `runtimeId: claude-code` (via `metadata`) to match the\n * other Claude config readers. Runtime tags are source metadata only; Shipyard\n * registers and pushes the full enabled MCP set to every agent profile.\n */\nexport async function readClaudeJsonLocalMcpServers(\n filePath: string,\n envPaths: readonly string[],\n log: Log,\n metadata: MCPSourceMetadata,\n now: () => number = Date.now\n): Promise<MCPServerInfo[]> {\n if (envPaths.length === 0) return [];\n /**\n * Stable cache key — `readMCPConfig` already caches this same file under its\n * bare `filePath` for the top-level `mcpServers` read, so `::local` keeps the\n * two from colliding. The env set rides in `cacheVariant` (not the key) so\n * adding/removing a worktree re-validates this ONE entry instead of orphaning\n * a per-env-set key in the long-lived cache.\n */\n const envVariant = [...envPaths].sort().join('\\n');\n return readCachedMcpConfig(\n filePath,\n 'local',\n log,\n (raw) => {\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; projects/mcpServers validated per-entry below\n const json = JSON.parse(raw) as Record<string, unknown>;\n return parseClaudeJsonLocalEntries(json, envPaths, metadata);\n },\n now,\n `${filePath}::local`,\n envVariant\n );\n}\n\nexport async function readCodexMCPConfig(\n filePath: string,\n source: MCPServerSource,\n log: Log,\n metadata: MCPSourceMetadata,\n now: () => number = Date.now\n): Promise<MCPServerInfo[]> {\n return readCachedMcpConfig(\n filePath,\n source,\n log,\n (raw) => {\n const parsed = parseTomlRecord(raw);\n return isObjectRecord(parsed.mcp_servers)\n ? validateCodexEntries(parsed.mcp_servers, source, metadata)\n : { servers: [], invalid: [] };\n },\n now\n );\n}\n\n/**\n * Cursor's `~/.cursor/mcp.json` (and project `.cursor/mcp.json`) uses the same\n * `mcpServers` wrapper as Claude, but its remote entries are commonly written as\n * a bare `{ \"url\": \"...\" }` with NO `type` field — Cursor infers a streamable-\n * HTTP transport from the URL. The shared `MCPServerEntrySchema` requires an\n * explicit `type: 'http' | 'sse'` for url entries, so a typeless Cursor entry\n * would be rejected as invalid and silently dropped. Normalize typeless-url\n * entries to `type: 'http'` before validation so they survive. Entries that\n * already declare a `type`, or stdio entries with a `command`, pass through\n * unchanged.\n */\nfunction normalizeCursorEntries(entries: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(entries)) {\n if (\n isObjectRecord(value) &&\n typeof value.url === 'string' &&\n value.type === undefined &&\n value.command === undefined\n ) {\n out[name] = { ...value, type: 'http' };\n } else {\n out[name] = value;\n }\n }\n return out;\n}\n\n/**\n * Read Cursor's MCP config (`~/.cursor/mcp.json` or project `.cursor/mcp.json`).\n *\n * Servers are tagged with NO `runtimeId` (shared) so a developer migrating from\n * the Cursor CLI keeps their MCP servers AND gets them on EVERY agent (Claude +\n * Codex + Cursor), matching the cross-tool behaviour of `~/.mcp.json`.\n */\nexport async function readCursorMCPConfig(\n filePath: string,\n source: MCPServerSource,\n log: Log,\n metadata: MCPSourceMetadata,\n now: () => number = Date.now\n): Promise<MCPServerInfo[]> {\n return readCachedMcpConfig(\n filePath,\n source,\n log,\n (raw) => {\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; validated per-entry below\n const json = JSON.parse(raw) as Record<string, unknown>;\n const entries = isObjectRecord(json.mcpServers) ? json.mcpServers : null;\n return entries === null\n ? { servers: [], invalid: [] }\n : validateJsonEntries(normalizeCursorEntries(entries), source, metadata);\n },\n now\n );\n}\n\nasync function readPluginMCPServers(log: Log): Promise<MCPServerInfo[]> {\n const servers: MCPServerInfo[] = [];\n try {\n const settingsPath = join(homedir(), '.claude', 'settings.json');\n const settingsRaw = await readFile(settingsPath, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; checking enabledPlugins field only\n const settings = JSON.parse(settingsRaw) as { enabledPlugins?: Record<string, boolean> };\n if (!settings.enabledPlugins) return [];\n\n const installedPath = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');\n const installedRaw = await readFile(installedPath, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; checking plugins field only\n const installed = JSON.parse(installedRaw) as {\n plugins?: Record<string, Array<{ installPath?: string }>>;\n };\n if (!installed.plugins) return [];\n\n for (const [pluginId, enabled] of Object.entries(settings.enabledPlugins)) {\n if (!enabled) continue;\n const installs = installed.plugins[pluginId];\n if (!installs || installs.length === 0) continue;\n const installPath = installs[0]?.installPath;\n if (!installPath) continue;\n\n const mcpJsonPath = join(installPath, '.mcp.json');\n const pluginServers = await readMCPConfig(mcpJsonPath, 'plugin', log, {\n sourceLabel: 'Plugin',\n sourcePath: '~/.claude/plugins/',\n });\n servers.push(...pluginServers);\n }\n } catch {}\n return servers;\n}\n\nconst CodexMarketplaceEntrySchema = z.object({\n source: z.string(),\n source_type: z.string().optional(),\n});\n\nconst CodexMarketplacesSchema = z.record(z.string(), CodexMarketplaceEntrySchema.passthrough());\n\nconst CodexPluginEntrySchema = z.object({\n enabled: z.boolean().optional(),\n});\n\nconst CodexPluginsSchema = z.record(z.string(), CodexPluginEntrySchema.passthrough());\n\nconst CodexConfigTomlSchema = z.object({\n mcp_servers: z.record(z.string(), z.unknown()).optional(),\n marketplaces: CodexMarketplacesSchema.optional(),\n plugins: CodexPluginsSchema.optional(),\n});\n\ntype CodexConfigToml = z.infer<typeof CodexConfigTomlSchema>;\n\nconst MarketplaceJsonPluginSourceSchema = z.object({\n source: z.string(),\n path: z.string(),\n});\n\nconst MarketplaceJsonPluginSchema = z.object({\n name: z.string(),\n source: MarketplaceJsonPluginSourceSchema.optional(),\n});\n\nconst MarketplaceJsonSchema = z.object({\n name: z.string().optional(),\n plugins: z.array(MarketplaceJsonPluginSchema),\n});\n\nconst CodexPluginManifestSchema = z.object({\n mcpServers: z.string().optional(),\n skills: z.string().optional(),\n});\n\nconst CodexPluginMcpServersFileSchema = z.object({\n mcpServers: z.record(z.string(), z.unknown()).optional(),\n});\n\nasync function readCodexTomlConfig(configPath: string): Promise<CodexConfigToml | null> {\n try {\n const raw = await readFile(configPath, 'utf-8');\n const parsed = parseTomlRecord(raw);\n const result = CodexConfigTomlSchema.safeParse(parsed);\n return result.success ? result.data : null;\n } catch {\n return null;\n }\n}\n\nasync function readMarketplaceJson(\n marketplaceSourceDir: string\n): Promise<z.infer<typeof MarketplaceJsonSchema> | null> {\n const candidates = [\n join(marketplaceSourceDir, '.agents', 'plugins', 'marketplace.json'),\n join(marketplaceSourceDir, 'marketplace.json'),\n ];\n for (const candidate of candidates) {\n try {\n const raw = await readFile(candidate, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; validated by schema\n const parsed = JSON.parse(raw) as unknown;\n const result = MarketplaceJsonSchema.safeParse(parsed);\n if (result.success) return result.data;\n } catch {}\n }\n return null;\n}\n\n/**\n * Read MCP servers from a Codex plugin's manifest and mcp file.\n * Returns an empty array (and logs) if any step fails — one bad plugin\n * must not block the rest of detection.\n */\nasync function readCodexPluginManifestMcps(\n pluginRoot: string,\n pluginId: string,\n marketplaceName: string,\n log: Log\n): Promise<MCPServerInfo[]> {\n const manifestPath = join(pluginRoot, '.codex-plugin', 'plugin.json');\n try {\n const raw = await readFile(manifestPath, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; validated by schema\n const parsed = JSON.parse(raw) as unknown;\n const manifestResult = CodexPluginManifestSchema.safeParse(parsed);\n if (!manifestResult.success) {\n log({\n event: 'codex_plugin_manifest_invalid',\n pluginId,\n marketplaceName,\n error: manifestResult.error.message,\n });\n return [];\n }\n const manifest = manifestResult.data;\n if (!manifest.mcpServers) return [];\n\n const mcpFilePath = resolve(pluginRoot, manifest.mcpServers);\n try {\n const mcpRaw = await readFile(mcpFilePath, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; validated by schema\n const mcpParsed = JSON.parse(mcpRaw) as unknown;\n const mcpResult = CodexPluginMcpServersFileSchema.safeParse(mcpParsed);\n if (!mcpResult.success || !mcpResult.data.mcpServers) return [];\n\n const sourceLabel = `Codex Plugin (${pluginId})`;\n const sourcePath = `~/.codex/plugins/${pluginId}`;\n /**\n * Codex plugin MCP declarations are standard MCP transports. Import them\n * as shared workspace servers so migrating Codex users can use the same\n * servers from Claude, Codex, and Cursor profiles.\n */\n const { servers, invalid } = validateCodexEntries(mcpResult.data.mcpServers, 'plugin', {\n sourceLabel,\n sourcePath,\n });\n if (invalid.length > 0) {\n log({\n event: 'codex_plugin_mcp_entries_invalid',\n pluginId,\n marketplaceName,\n invalidCount: invalid.length,\n errors: invalid.slice(0, 3),\n });\n }\n return servers;\n } catch {\n log({ event: 'codex_plugin_mcp_file_unreadable', pluginId, marketplaceName, mcpFilePath });\n return [];\n }\n } catch {\n /**\n * Plugin manifest missing — not an error, just not configured.\n * Absence of `.codex-plugin/plugin.json` is the common case for repos\n * that don't declare Codex plugins, so this catch is intentionally silent.\n */\n return [];\n }\n}\n\n/**\n * Detect MCP servers declared by Codex marketplace plugins.\n *\n * Reads `configToml.marketplaces` → finds each marketplace's `marketplace.json`\n * → resolves local plugin paths → reads each plugin's `.codex-plugin/plugin.json`\n * → reads the `mcpServers` file referenced by the manifest.\n *\n * Only processes plugins where `configToml.plugins[\"pluginName@marketplaceName\"]?.enabled`\n * is `true` (or absent — omitted entry means enabled by default in Codex).\n *\n * Errors in any single plugin are logged and skipped; a bad plugin never\n * blocks the rest of detection.\n */\nexport async function detectCodexPluginMcps(\n codexHome: string,\n configToml: CodexConfigToml,\n log: Log\n): Promise<MCPServerInfo[]> {\n const marketplaces = configToml.marketplaces;\n if (!marketplaces || Object.keys(marketplaces).length === 0) return [];\n\n const pluginEnabledMap = configToml.plugins ?? {};\n const allServers: MCPServerInfo[] = [];\n\n await Promise.all(\n Object.entries(marketplaces).map(async ([marketplaceName, marketplaceEntry]) => {\n if (marketplaceEntry.source_type && marketplaceEntry.source_type !== 'local') return;\n\n const marketplaceSourceDir = marketplaceEntry.source;\n if (!marketplaceSourceDir) return;\n\n const marketplaceJson = await readMarketplaceJson(marketplaceSourceDir);\n if (!marketplaceJson) {\n log({ event: 'codex_marketplace_json_missing', marketplaceName, marketplaceSourceDir });\n return;\n }\n\n await Promise.all(\n marketplaceJson.plugins.map(async (plugin) => {\n if (!plugin.source || plugin.source.source !== 'local') return;\n\n const pluginId = `${plugin.name}@${marketplaceName}`;\n const pluginEnabledEntry = pluginEnabledMap[pluginId];\n /** Codex treats absence of a plugins entry as enabled; only skip if explicitly disabled. */\n if (pluginEnabledEntry?.enabled === false) return;\n\n const pluginRoot = resolve(marketplaceSourceDir, plugin.source.path);\n const servers = await readCodexPluginManifestMcps(\n pluginRoot,\n pluginId,\n marketplaceName,\n log\n );\n allServers.push(...servers);\n })\n );\n })\n );\n\n if (allServers.length > 0) {\n log({ event: 'codex_plugin_mcps_detected', count: allServers.length, codexHome });\n }\n\n return allServers;\n}\n\nfunction pushCandidates(\n target: DetectedServerCandidate[],\n servers: MCPServerInfo[],\n priority: number\n): void {\n for (const server of servers) {\n target.push({ server, priority });\n }\n}\n\n/**\n * Check Claude Code's credential store for servers that still have\n * `authStatus === 'unknown'` after checking Shipyard's own token store.\n * If Claude Code has a valid (non-expired) token, mark the server as authenticated.\n */\nasync function resolveClaudeCodeAuthStatuses(servers: Map<string, MCPServerInfo>): Promise<void> {\n for (const server of servers.values()) {\n if (server.authStatus !== 'unknown') continue;\n if (server.type === 'stdio') continue;\n const ccCreds = await readClaudeCodeCredentials(server.name, server.url ?? '');\n if (ccCreds?.accessToken && ccCreds.expiresAt && ccCreds.expiresAt > Date.now()) {\n server.authStatus = 'authenticated';\n }\n }\n}\n\nfunction resolveStdioAuthStatus(\n server: MCPServerInfo,\n tokens: Record<string, import('../mcp/token-store.js').MCPOAuthToken>,\n tokenStore: import('../mcp/token-store.js').MCPTokenStore\n): void {\n if (!server.env) return;\n for (const value of Object.values(server.env)) {\n const match = VAULT_REF_PATTERN.exec(value);\n if (!match) continue;\n const vaultKey = match[1] ?? '';\n const token = tokens[vaultKey];\n if (token) {\n server.authStatus = tokenStore.isExpired(token) ? 'unauthenticated' : 'authenticated';\n return;\n }\n }\n}\n\nasync function resolveAuthStatuses(\n servers: Map<string, MCPServerInfo>,\n tokenStore: import('../mcp/token-store.js').MCPTokenStore\n): Promise<void> {\n const tokens = await tokenStore.getAllTokens();\n for (const server of servers.values()) {\n if (server.type === 'stdio') {\n resolveStdioAuthStatus(server, tokens, tokenStore);\n continue;\n }\n const token =\n tokens[server.name] ?? (server.url ? selectTokenByUrl(tokens, server.url, Date.now()) : null);\n if (token) {\n server.authStatus = tokenStore.isExpired(token) ? 'unauthenticated' : 'authenticated';\n }\n }\n\n await resolveClaudeCodeAuthStatuses(servers);\n}\n\n/**\n * Detect MCP servers across user/project/plugin/claude.ai sources.\n *\n * `lastKnown` preserves the previously-detected MCP server list when the\n * detection itself throws (rare — readMCPConfig swallows its own errors —\n * but defense in depth against future regressions and unhandled rejections\n * inside `fetchClaudeAiIntegrations`). Mirror of the `lastKnownAgents`\n * pattern in `agents.ts`.\n *\n * Note: under normal operation, errors are swallowed inside the per-file\n * readers, so this function reaches the dedupe step with a possibly-empty\n * but well-shaped `allServers`. The `try/catch` here is the chokepoint that\n * catches anything escaping that — particularly account-integrations\n * fetches that hit the network.\n */\nexport async function detectMCPServers(\n environments: GitRepoInfo[],\n tokenStore: import('../mcp/token-store.js').MCPTokenStore | undefined,\n log: Log,\n lastKnown: MCPServerInfo[] | undefined,\n /**\n * Gates the `fetchClaudeAiIntegrations` network fetch (Connectors page on\n * claude.ai). The fetch only succeeds with claude.ai OAuth tokens; for\n * console / api-key / SSO users it 401s and floods logs every refresh tick.\n *\n * Skipped when the user's chosen method is anything other than 'claude-ai'.\n * `null`/`undefined` (preference unknown — not yet backfilled) keeps the\n * current behaviour of attempting the fetch so OAuth users still get their\n * connectors before the boot-time backfill lands.\n */\n preferredAuth?: AnthropicAuthMethod | null,\n /**\n * Incremental scope: when set, only the project-level files at\n * `changedCwd` are re-scanned. Project entries from all OTHER environments\n * are reused from `lastKnown`. The global slices (user / plugin /\n * claude.ai) are still re-scanned in full because they're cheap and\n * commonly change between refreshes.\n *\n * Wired through `refreshMcpServers` from `buildCwdScopedPatch` so the\n * worktree-creation cwd refresh skips the O(envs) project scan that\n * dominated the 1.3-2.5s scoped-refresh budget on a 180-worktree machine.\n * When unset (production default for full refresh and capability\n * watcher), behaviour matches the pre-incremental path.\n */\n changedCwd?: string\n): Promise<MCPServerInfo[]> {\n try {\n return await detectMCPServersInner(\n environments,\n tokenStore,\n log,\n preferredAuth,\n changedCwd,\n lastKnown\n );\n } catch (err) {\n /**\n * Preserve the original \"always resolves\" contract: inner readers\n * already swallow per-file errors and return [], so this catch only\n * fires for unhandled rejections (network failure in\n * `fetchClaudeAiIntegrations`, future regressions). Returning\n * lastKnown if available, otherwise [] — never rethrow, because the\n * Promise.all in detectCapabilities would tear down the whole refresh\n * for a single slice's failure.\n */\n const { logger } = await import('../logger.js');\n if (lastKnown && lastKnown.length > 0) {\n logger.warn(\n { err, lastKnownCount: lastKnown.length },\n 'detectMCPServers threw — preserving lastKnown'\n );\n return lastKnown;\n }\n logger.debug({ err }, 'detectMCPServers threw with no lastKnown — returning []');\n return [];\n }\n}\n\n/** Build a display label like \"Claude Code User\" or \"Codex Local\" for a runtime-owned config scope. */\nfunction runtimeScopeLabel(runtimeId: string, scope: string): string {\n return `${getRuntimeDisplayName(runtimeId)} ${scope}`;\n}\n\n/**\n * Priority used when injecting `lastKnown` entries into the candidate pool\n * for the incremental cwd path. Project-tier sources are mapped to the\n * same priority a fresh per-env scan would assign so the dedupe matches\n * the non-incremental output for environments we deliberately skipped.\n *\n * Globals (claudeai/plugin/user) keep their original priorities; their\n * fresh re-scan ALWAYS runs in the incremental path, so the lastKnown\n * entry is overwritten via `>=` regardless of exact mapping. Mapping is\n * still provided for correctness when `lastKnown` includes a global\n * source that the fresh scan happens to miss (e.g. transient claude.ai\n * fetch failure).\n */\nconst SOURCE_PRIORITY_FOR_LASTKNOWN: Record<MCPServerSource, number> = {\n claudeai: 10,\n plugin: 20,\n user: 30,\n project: 50,\n /**\n * `local` now covers three push sites: `~/.claude/settings.local.json` (pushed\n * at 31), `.claude/settings.local.json` (env loop, 60), and `~/.claude.json`'s\n * `projects[cwd].mcpServers` (60). Seeding all at 60 is safe — a same-name\n * collision across these is vanishingly rare, and the fresh re-scan re-pushes\n * the live entry, so the seed only matters for sources skipped by an\n * incremental scan (which the project-tier ones are not).\n */\n local: 60,\n 'mcp-json': 70,\n};\n\n/**\n * Seed the candidate pool with prior-known entries for the incremental\n * scan path. Must be called BEFORE any fresh-scan candidates are pushed\n * so the fresh entries dedupe-win via the `>=` priority comparison in\n * the dedupe loop.\n */\nfunction seedLastKnownCandidates(\n target: DetectedServerCandidate[],\n lastKnown: MCPServerInfo[] | undefined\n): void {\n if (!lastKnown) return;\n for (const server of lastKnown) {\n target.push({ server, priority: SOURCE_PRIORITY_FOR_LASTKNOWN[server.source] });\n }\n}\n\n/**\n * Read the four project-tier config files for a single environment in\n * parallel. Extracted from `detectMCPServersInner` so that function stays\n * under the cognitive-complexity ceiling — the per-file metadata blocks\n * are unwieldy inline.\n */\nfunction readEnvProjectMcpFiles(\n env: GitRepoInfo,\n log: Log\n): Promise<[MCPServerInfo[], MCPServerInfo[], MCPServerInfo[], MCPServerInfo[], MCPServerInfo[]]> {\n const projectPath = join(env.path, '.claude', 'settings.json');\n const localPath = join(env.path, '.claude', 'settings.local.json');\n const codexProjectPath = join(env.path, '.codex', 'config.toml');\n const mcpJsonPath = join(env.path, '.mcp.json');\n const cursorMcpJsonPath = join(env.path, '.cursor', 'mcp.json');\n return Promise.all([\n readMCPConfig(projectPath, 'project', log, {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n sourceLabel: runtimeScopeLabel(CLAUDE_CODE_RUNTIME_ID, 'Project'),\n sourcePath: '.claude/settings.json',\n }),\n readMCPConfig(localPath, 'local', log, {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n sourceLabel: runtimeScopeLabel(CLAUDE_CODE_RUNTIME_ID, 'Local'),\n sourcePath: '.claude/settings.local.json',\n }),\n readCodexMCPConfig(codexProjectPath, 'project', log, {\n sourceLabel: 'Codex Project',\n sourcePath: '.codex/config.toml',\n }),\n readMCPConfig(mcpJsonPath, 'mcp-json', log, {\n sourceLabel: 'Project',\n sourcePath: '.mcp.json',\n }),\n readCursorMCPConfig(cursorMcpJsonPath, 'project', log, {\n sourceLabel: 'Cursor Project',\n sourcePath: '.cursor/mcp.json',\n }),\n ]);\n}\n\nasync function detectMCPServersInner(\n environments: GitRepoInfo[],\n tokenStore: import('../mcp/token-store.js').MCPTokenStore | undefined,\n log: Log,\n preferredAuth: AnthropicAuthMethod | null | undefined,\n changedCwd: string | undefined,\n lastKnown: MCPServerInfo[] | undefined\n): Promise<MCPServerInfo[]> {\n const allCandidates: DetectedServerCandidate[] = [];\n\n /**\n * Incremental path: seed the candidate pool with prior-known entries so\n * project-tier servers from environments we won't re-scan persist.\n *\n * Note: project-tier removals at `changedCwd` are NOT propagated here —\n * seeded entries for that path survive if the fresh scan doesn't produce\n * a same-named replacement. This is safe because `changedCwd` is only\n * supplied on worktree **creation** (new path, no prior servers to remove).\n * Removals from existing paths arrive via `capability_watcher_mcp` which\n * calls `detectMCPServers` without `changedCwd` (full rescan).\n */\n if (changedCwd) seedLastKnownCandidates(allCandidates, lastKnown);\n\n const userSettingsPath = join(homedir(), '.claude', 'settings.json');\n const userLocalSettingsPath = join(homedir(), '.claude', 'settings.local.json');\n const userCodexConfigPath = join(homedir(), '.codex', 'config.toml');\n const userMcpJsonPath = join(homedir(), '.mcp.json');\n const userCursorMcpJsonPath = join(homedir(), '.cursor', 'mcp.json');\n const userClaudeJsonPath = join(homedir(), '.claude.json');\n const codexHome = join(homedir(), '.codex');\n\n /**\n * Only the claude.ai OAuth flow exposes the Connectors page that\n * `fetchClaudeAiIntegrations` reads. Console / api-key / SSO / cloud-provider\n * users would 401 and produce log noise on every refresh tick. `null` (not\n * yet backfilled) and `undefined` (caller didn't plumb through) keep the\n * legacy behaviour to preserve OAuth users' connectors during rollout.\n */\n const fetchClaudeAi = shouldFetchClaudeAiIntegrations(preferredAuth);\n const claudeAiPromise: Promise<MCPServerInfo[]> = fetchClaudeAi\n ? fetchClaudeAiIntegrations(log)\n : Promise.resolve([]);\n if (!fetchClaudeAi) {\n log({ event: 'claudeai_integrations_skipped_by_method', method: preferredAuth ?? null });\n }\n\n /**\n * Read the Codex config once so we can pass it to both the MCP reader and\n * the plugin-marketplace traversal without hitting disk twice.\n */\n const codexUserConfig = await readCodexTomlConfig(userCodexConfigPath);\n\n const [\n userServers,\n userLocalServers,\n userClaudeJsonServers,\n userCodexServers,\n userMcpJsonServers,\n userCursorServers,\n pluginServers,\n codexPluginServers,\n claudeAiServers,\n claudeJsonLocalServers,\n ] = await Promise.all([\n readMCPConfig(userSettingsPath, 'user', log, {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n sourceLabel: runtimeScopeLabel(CLAUDE_CODE_RUNTIME_ID, 'User'),\n sourcePath: '~/.claude/settings.json',\n }),\n readMCPConfig(userLocalSettingsPath, 'user', log, {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n sourceLabel: runtimeScopeLabel(CLAUDE_CODE_RUNTIME_ID, 'Local'),\n sourcePath: '~/.claude/settings.local.json',\n }),\n readMCPConfig(userClaudeJsonPath, 'user', log, {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n sourceLabel: runtimeScopeLabel(CLAUDE_CODE_RUNTIME_ID, 'User'),\n sourcePath: '~/.claude.json',\n }),\n readCodexMCPConfig(userCodexConfigPath, 'user', log, {\n sourceLabel: 'Codex User',\n sourcePath: '~/.codex/config.toml',\n }),\n readMCPConfig(userMcpJsonPath, 'user', log, {\n sourceLabel: 'User',\n sourcePath: '~/.mcp.json',\n }),\n readCursorMCPConfig(userCursorMcpJsonPath, 'user', log, {\n sourceLabel: 'Cursor User',\n sourcePath: '~/.cursor/mcp.json',\n }),\n readPluginMCPServers(log),\n codexUserConfig ? detectCodexPluginMcps(codexHome, codexUserConfig, log) : Promise.resolve([]),\n claudeAiPromise,\n readClaudeJsonLocalMcpServers(\n userClaudeJsonPath,\n environments.map((env) => env.path),\n log,\n {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n sourceLabel: runtimeScopeLabel(CLAUDE_CODE_RUNTIME_ID, 'Local'),\n sourcePath: '~/.claude.json',\n }\n ),\n ]);\n pushCandidates(allCandidates, claudeAiServers, 10);\n pushCandidates(allCandidates, pluginServers, 20);\n pushCandidates(allCandidates, codexPluginServers, 25);\n pushCandidates(allCandidates, userServers, 30);\n pushCandidates(allCandidates, userLocalServers, 31);\n pushCandidates(allCandidates, userClaudeJsonServers, 32);\n pushCandidates(allCandidates, userCodexServers, 33);\n pushCandidates(allCandidates, userMcpJsonServers, 40);\n pushCandidates(allCandidates, userCursorServers, 41);\n /**\n * Local-scope (`projects[cwd].mcpServers`) is `source: 'local'`, so push at\n * the same priority the incremental-path seed assigns that source\n * (SOURCE_PRIORITY_FOR_LASTKNOWN['local'] = 60). Equal priority lets a fresh\n * read win over a stale seed via the dedupe loop's `>=`, and matches Claude\n * Code's local > user precedence on a same-named collision.\n */\n pushCandidates(allCandidates, claudeJsonLocalServers, 60);\n\n /**\n * Incremental path: only the env at `changedCwd` is re-scanned. All other\n * environments' project-tier entries come from the `lastKnown` seed above.\n */\n const envsToScan = changedCwd\n ? environments.filter((env) => env.path === changedCwd)\n : environments;\n const envResults = await Promise.all(envsToScan.map((env) => readEnvProjectMcpFiles(env, log)));\n for (const [\n projectServers,\n localServers,\n codexProjectServers,\n mcpJsonServers,\n cursorProjectServers,\n ] of envResults) {\n pushCandidates(allCandidates, projectServers, 50);\n pushCandidates(allCandidates, localServers, 60);\n pushCandidates(allCandidates, codexProjectServers, 65);\n pushCandidates(allCandidates, mcpJsonServers, 70);\n pushCandidates(allCandidates, cursorProjectServers, 71);\n }\n\n const survivors = dedupeServerCandidates(allCandidates);\n\n if (tokenStore) {\n await resolveAuthStatuses(\n new Map(survivors.map((server) => [server.name, server])),\n tokenStore\n );\n }\n\n return survivors;\n}\n","import { execFile as execFileCb } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport type { OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';\nimport { z } from 'zod';\n\nimport { isClaudeCodeKeychainReadEnabled } from '../env.js';\nimport { logger } from '../logger.js';\nimport { DiscoveryStateSchema } from './schemas.js';\n\nconst execFile = promisify(execFileCb);\n\n/**\n * Represents a single OAuth entry from Claude Code's credential store.\n *\n * Claude Code v2.1.81+ stores credentials in macOS Keychain under\n * service name \"Claude Code-credentials\". Older versions used\n * `~/.claude/.credentials.json`.\n *\n * The format is owned by Claude Code and may change without notice.\n * All fields are optional to tolerate schema drift.\n */\nexport interface ClaudeCodeOAuthEntry {\n serverName: string;\n serverUrl: string;\n clientId?: string;\n clientSecret?: string;\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: number;\n discoveryState?: OAuthDiscoveryState;\n}\n\n/**\n * Schema for a single entry in `mcpOAuth`. We use `.passthrough()` so\n * unknown future fields are preserved.\n *\n * CC stores `null` for cleared fields (e.g., `accessToken: null` after\n * logout). Zod's `.optional()` only accepts `undefined`, not `null`,\n * so we must use `.nullable().optional()` to tolerate both.\n */\nconst ClaudeCodeOAuthEntrySchema = z\n .object({\n serverName: z.string().nullable().optional(),\n serverUrl: z.string().nullable().optional(),\n clientId: z.string().nullable().optional(),\n clientSecret: z.string().nullable().optional(),\n accessToken: z.string().nullable().optional(),\n refreshToken: z.string().nullable().optional(),\n expiresAt: z.number().nullable().optional(),\n discoveryState: DiscoveryStateSchema.nullable().optional(),\n })\n .passthrough();\n\nconst CredentialsFileSchema = z\n .object({\n mcpOAuth: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\nconst CREDENTIALS_PATH = join(homedir(), '.claude', '.credentials.json');\nconst KEYCHAIN_SERVICE = 'Claude Code-credentials';\n\nconst PluginMcpJsonSchema = z.record(\n z.string(),\n z\n .object({\n url: z.string().optional(),\n oauth: z.object({ clientId: z.string(), callbackPort: z.number().optional() }).optional(),\n })\n .passthrough()\n);\n\n/**\n * OAuth config a CC plugin `.mcp.json` pre-registers for a server. `clientId`\n * is a pre-registered (often static, e.g. Slack) OAuth app; `callbackPort` is\n * the fixed loopback port that app's redirect_uris were registered against.\n * Servers like Slack do exact redirect_uri matching, so the port MUST be\n * honored — a random port produces \"redirect_uri did not match\" failures.\n */\nexport interface PluginOAuthConfig {\n clientId: string;\n callbackPort?: number;\n}\n\n/**\n * Read OAuth configs from CC plugin `.mcp.json` files.\n * Returns a Map from server URL to its pre-registered client + callback port.\n */\nasync function extractOAuthConfigsFromPlugin(\n installPath: string,\n result: Map<string, PluginOAuthConfig>\n): Promise<void> {\n const raw = await readFile(join(installPath, '.mcp.json'), 'utf-8');\n const json: unknown = JSON.parse(raw);\n const outer = z.record(z.string(), z.unknown()).safeParse(json);\n if (!outer.success) return;\n const servers = outer.data.mcpServers ?? outer.data;\n const validated = PluginMcpJsonSchema.safeParse(servers);\n if (!validated.success) return;\n\n for (const config of Object.values(validated.data)) {\n if (config.url && config.oauth?.clientId) {\n result.set(config.url, {\n clientId: config.oauth.clientId,\n callbackPort: config.oauth.callbackPort,\n });\n }\n }\n}\n\nexport async function readPluginOAuthConfigs(): Promise<Map<string, PluginOAuthConfig>> {\n const result = new Map<string, PluginOAuthConfig>();\n try {\n const installedPath = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');\n const InstalledPluginsSchema = z.object({\n plugins: z\n .record(z.string(), z.array(z.object({ installPath: z.string().optional() })))\n .optional(),\n });\n const parsed = InstalledPluginsSchema.safeParse(\n JSON.parse(await readFile(installedPath, 'utf-8'))\n );\n if (!parsed.success || !parsed.data.plugins) return result;\n\n for (const installs of Object.values(parsed.data.plugins)) {\n const installPath = installs?.[0]?.installPath;\n if (!installPath) continue;\n await extractOAuthConfigsFromPlugin(installPath, result).catch(() => {});\n }\n } catch {}\n return result;\n}\n\n/**\n * Attempt to read Claude Code's credential blob from macOS Keychain.\n * Returns the parsed JSON object or null if unavailable.\n */\nasync function readKeychainCredentials(): Promise<Record<string, unknown> | null> {\n if (process.platform !== 'darwin') return null;\n /**\n * Reading CC's Keychain item from the daemon (a different binary) triggers a\n * macOS password prompt in a GUI session. Off by default — see\n * `isClaudeCodeKeychainReadEnabled`. Shipyard's own token store is the source\n * of truth; the URL-keyed fallback there finds tokens CC wrote regardless of\n * display-name casing, so this path is no longer needed for the common case.\n */\n if (!isClaudeCodeKeychainReadEnabled()) return null;\n\n try {\n const { stdout } = await execFile(\n 'security',\n ['find-generic-password', '-s', KEYCHAIN_SERVICE, '-w'],\n { timeout: 5_000 }\n );\n const result = z.record(z.string(), z.unknown()).safeParse(JSON.parse(stdout.trim()));\n return result.success ? result.data : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Search a parsed credentials object for the best MCP OAuth entry\n * matching the given `serverUrl`. Prefers entries with an access token;\n * separately gathers clientId from any matching entry.\n *\n * CC stores entries under both bare (`slack`) and plugin-prefixed\n * (`plugin:slack:slack`) keys. The prefixed entries typically have\n * tokens while the bare entries may only have clientId. We merge\n * across all matching entries to get the most complete picture.\n */\n/** Scan a flat mcpOAuth record for entries matching serverUrl. */\nfunction scanEntries(\n mcpOAuth: Record<string, unknown>,\n serverUrl: string\n): {\n bestWithToken: z.infer<typeof ClaudeCodeOAuthEntrySchema> | null;\n clientId?: string;\n clientSecret?: string;\n discoveryState?: OAuthDiscoveryState;\n} {\n let bestWithToken: z.infer<typeof ClaudeCodeOAuthEntrySchema> | null = null;\n let clientId: string | undefined;\n let clientSecret: string | undefined;\n let discoveryState: OAuthDiscoveryState | undefined;\n\n for (const value of Object.values(mcpOAuth)) {\n const entryResult = ClaudeCodeOAuthEntrySchema.safeParse(value);\n if (!entryResult.success) continue;\n\n const entry = entryResult.data;\n if (entry.serverUrl !== serverUrl) continue;\n\n if (entry.clientId && !clientId) {\n clientId = entry.clientId;\n clientSecret = entry.clientSecret || undefined;\n }\n if (entry.discoveryState && !discoveryState) {\n discoveryState = entry.discoveryState;\n }\n if (entry.accessToken && !bestWithToken) {\n bestWithToken = entry;\n }\n }\n\n return { bestWithToken, clientId, clientSecret, discoveryState };\n}\n\nfunction findMatchingEntry(\n credentialsData: Record<string, unknown>,\n serverName: string,\n serverUrl: string\n): ClaudeCodeOAuthEntry | null {\n const fileResult = CredentialsFileSchema.safeParse(credentialsData);\n if (!fileResult.success) return null;\n\n const mcpOAuth = fileResult.data.mcpOAuth;\n if (!mcpOAuth) return null;\n\n const { bestWithToken, clientId, clientSecret, discoveryState } = scanEntries(\n mcpOAuth,\n serverUrl\n );\n if (!bestWithToken && !clientId) return null;\n\n return {\n serverName: bestWithToken?.serverName ?? serverName,\n serverUrl,\n clientId: bestWithToken?.clientId || clientId,\n clientSecret: bestWithToken?.clientSecret || clientSecret || undefined,\n accessToken: bestWithToken?.accessToken || undefined,\n refreshToken: bestWithToken?.refreshToken || undefined,\n expiresAt: bestWithToken?.expiresAt ?? undefined,\n discoveryState: bestWithToken?.discoveryState ?? discoveryState ?? undefined,\n };\n}\n\n/**\n * Search Claude Code's credential store for an MCP OAuth entry\n * matching the given `serverUrl`.\n *\n * Tries macOS Keychain first (Claude Code v2.1.81+, only when\n * `SHIPYARD_MCP_REUSE_CC_KEYCHAIN` is set — off by default to avoid the\n * password prompt), then falls back to the legacy file at\n * `~/.claude/.credentials.json`.\n *\n * Keys in the store use hashes we cannot reproduce, so we match\n * by `serverUrl` instead. Returns the first entry whose `serverUrl`\n * matches and that has a non-empty `clientId`.\n */\nexport async function readClaudeCodeCredentials(\n serverName: string,\n serverUrl: string\n): Promise<ClaudeCodeOAuthEntry | null> {\n if (!serverUrl) return null;\n\n try {\n const keychainData = await readKeychainCredentials();\n if (keychainData) {\n const entry = findMatchingEntry(keychainData, serverName, serverUrl);\n if (entry) {\n logger.debug({ serverUrl }, 'Found Claude Code credentials in macOS Keychain');\n return entry;\n }\n }\n } catch (err: unknown) {\n logger.debug({ err }, 'Failed to read Claude Code credentials from Keychain');\n }\n\n try {\n const raw = await readFile(CREDENTIALS_PATH, 'utf-8');\n const fileResult = CredentialsFileSchema.safeParse(JSON.parse(raw));\n if (fileResult.success) {\n const entry = findMatchingEntry(fileResult.data, serverName, serverUrl);\n if (entry) {\n logger.debug({ serverUrl }, 'Found Claude Code credentials in legacy file');\n return entry;\n }\n }\n\n return null;\n } catch (err: unknown) {\n logger.debug({ err }, 'Failed to read Claude Code credentials from file');\n return null;\n }\n}\n","import {\n OAuthMetadataSchema,\n OAuthProtectedResourceMetadataSchema,\n OpenIdProviderDiscoveryMetadataSchema,\n} from '@modelcontextprotocol/sdk/shared/auth.js';\nimport { z } from 'zod';\n\nexport const AuthorizationServerMetadataSchema = z.union([\n OAuthMetadataSchema,\n OpenIdProviderDiscoveryMetadataSchema,\n]);\n\nexport const DiscoveryStateSchema = z\n .object({\n authorizationServerUrl: z.string(),\n authorizationServerMetadata: AuthorizationServerMetadataSchema.optional(),\n resourceMetadata: OAuthProtectedResourceMetadataSchema.optional(),\n resourceMetadataUrl: z.string().optional(),\n })\n .passthrough();\n","import type { McpServerConfig } from '@anthropic-ai/claude-agent-sdk';\nimport type { MCPServerInfo } from '@shipyard/session';\n\nimport type { MCPTokenStore } from './token-store.js';\n\nexport const ENV_VAR_PATTERN = /\\$\\{([^}]+)\\}/g;\nexport const VAULT_REF_PATTERN = /^\\$\\{vault:([^}]+)\\}$/;\n\nexport function interpolateEnvVars(headers: Record<string, string>): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n result[key] = value.replace(\n ENV_VAR_PATTERN,\n (_, varName: string) => process.env[varName] ?? ''\n );\n }\n return result;\n}\n\n/**\n * Pass through user-configured static headers only. OAuth tokens for HTTP\n * servers are managed by the SDK subprocess via CC's Keychain — injecting\n * Shipyard's own tokens here would conflict with the SDK's OAuth transport.\n * Token store injection is only used for stdio env vars (resolveStdioEnv).\n */\nexport function resolveHeaders(server: MCPServerInfo): Record<string, string> | undefined {\n if (!server.headers) return undefined;\n return interpolateEnvVars(server.headers);\n}\n\nfunction resolveVaultRefEnvValue(\n key: string,\n value: string,\n store: MCPTokenStore,\n log?: (entry: { event: string; [key: string]: unknown }) => void\n): string | undefined {\n const match = VAULT_REF_PATTERN.exec(value);\n if (!match) return undefined;\n\n const vaultKey = match[1] ?? '';\n const token = store.getTokenSync(vaultKey);\n if (token && !store.isExpired(token)) {\n log?.({\n event: 'vault_ref_resolved',\n envKey: key,\n vaultKey,\n tokenType: token.tokenType,\n hasExpiry: token.expiresAt !== undefined,\n });\n return token.accessToken;\n }\n\n log?.({\n event: 'vault_ref_unresolved',\n envKey: key,\n vaultKey,\n tokenFound: token !== null,\n tokenExpired: token ? store.isExpired(token) : false,\n });\n return value;\n}\n\nexport function resolveStdioEnv(\n env: Record<string, string> | undefined,\n store?: MCPTokenStore,\n log?: (entry: { event: string; [key: string]: unknown }) => void\n): Record<string, string> | undefined {\n if (!env) return undefined;\n if (!store) return env;\n\n const result: Record<string, string> = {};\n let changed = false;\n\n for (const [key, value] of Object.entries(env)) {\n const vaultResolved = resolveVaultRefEnvValue(key, value, store, log);\n if (vaultResolved !== undefined) {\n result[key] = vaultResolved;\n if (vaultResolved !== value) {\n changed = true;\n }\n continue;\n }\n const interpolated = value.replace(\n ENV_VAR_PATTERN,\n (_, varName: string) => process.env[varName] ?? ''\n );\n result[key] = interpolated;\n if (interpolated !== value) {\n changed = true;\n }\n }\n\n return changed ? result : env;\n}\n\nfunction toResolvedMcpServerConfig(\n server: MCPServerInfo,\n mcpTokenStore?: MCPTokenStore\n): McpServerConfig | null {\n if (server.type === 'http' && server.url) {\n return {\n type: 'http',\n url: server.url,\n headers: resolveHeaders(server),\n };\n }\n if (server.type === 'sse' && server.url) {\n return {\n type: 'sse',\n url: server.url,\n headers: resolveHeaders(server),\n };\n }\n if (server.command) {\n return {\n command: server.command,\n args: server.args ?? undefined,\n env: resolveStdioEnv(server.env, mcpTokenStore),\n };\n }\n return null;\n}\n\nexport function resolveEnabledMcpServers(\n overrides: Array<{ name: string; enabled: boolean }> | undefined,\n available: MCPServerInfo[] | undefined,\n mcpTokenStore?: MCPTokenStore\n): Record<string, McpServerConfig> | undefined {\n if (!overrides || !available) return undefined;\n const enabledNames = new Set(overrides.filter((o) => o.enabled).map((o) => o.name));\n if (enabledNames.size === 0) return {};\n const result: Record<string, McpServerConfig> = {};\n for (const server of available) {\n if (!enabledNames.has(server.name)) continue;\n const config = toResolvedMcpServerConfig(server, mcpTokenStore);\n if (config) result[server.name] = config;\n }\n return result;\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport { readFile, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { atomicWriteFile, withFileLock } from '../fs-utils.js';\n\nexport interface MCPOAuthToken {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n tokenType: string;\n serverUrl: string;\n /** Cached client_id from dynamic client registration (RFC 7591). */\n clientId?: string;\n}\n\nexport type TokenMap = Record<string, MCPOAuthToken>;\n\ntype LogFn = (entry: { event: string; [key: string]: unknown }) => void;\n\nconst TOKEN_FILE = 'mcp-tokens.json';\nconst REFRESH_THRESHOLD_MS = 5 * 60 * 1_000;\n\n/**\n * Pure: pick the best token for a `serverUrl` from a name-keyed map.\n *\n * The same MCP server is stored under different display-name keys depending on\n * its source — claude.ai connectors use a capitalized name (`Figma`, `Slack`),\n * CC plugins use lowercase (`figma`, `slack`). The stable cross-source identity\n * is the `serverUrl`, so a name-keyed lookup miss must fall back to scanning by\n * URL or a valid token saved under a sibling casing is never found and the\n * connector is wrongly reported unauthenticated. Prefers a non-expired token,\n * then any token that at least carries an access token.\n */\nexport function selectTokenByUrl(\n tokens: TokenMap,\n serverUrl: string,\n now: number\n): MCPOAuthToken | null {\n if (!serverUrl) return null;\n let expiredFallback: MCPOAuthToken | null = null;\n for (const token of Object.values(tokens)) {\n if (token.serverUrl !== serverUrl || !token.accessToken) continue;\n const expired = token.expiresAt !== undefined && now >= token.expiresAt;\n if (!expired) return token;\n if (!expiredFallback) expiredFallback = token;\n }\n return expiredFallback;\n}\n\nexport class MCPTokenStore {\n #shipyardHome: string;\n #cache: TokenMap = {};\n #lastMtimeMs = -1;\n #log: LogFn;\n #onChange: ((serverName: string, token: MCPOAuthToken) => void) | null = null;\n /**\n * Serializes ALL mutations through a single promise chain. Without this,\n * concurrent writers (proxy proactive token refresh, oauth-provider\n * persistence, reauth-orchestrator setToken) can interleave read-modify-\n * write on `#cache` and race the file rename. The pre-fix code used a\n * shared `${filePath}.tmp` path which produced the 26 ENOENT errors per\n * 6-min window plus the 218 swallowed `cancelled` cascades observed in\n * the 2026-05-27 log triage — a second writer renamed its .tmp to the\n * same canonical path, and the first writer's rename then failed with\n * ENOENT. atomicWriteFile uses a PID+UUID tmp path so each writer owns\n * its own tmp; the mutation queue additionally prevents last-writer-wins\n * loss of in-flight cache mutations. Mirrors MCPOAuthStateStore.\n */\n #mutationQueue: Promise<void> = Promise.resolve();\n\n constructor(shipyardHome: string, log?: LogFn) {\n this.#shipyardHome = shipyardHome;\n this.#log = log ?? (() => {});\n }\n\n /**\n * Run `work` after all currently-queued mutations complete. A rejected\n * predecessor must NOT block subsequent mutations — chain on both fates.\n */\n #enqueueMutation<T>(work: () => Promise<T>): Promise<T> {\n const next = this.#mutationQueue.then(work, work);\n this.#mutationQueue = next.then(\n () => undefined,\n () => undefined\n );\n return next;\n }\n\n setOnChange(cb: ((serverName: string, token: MCPOAuthToken) => void) | null): void {\n this.#onChange = cb;\n }\n\n #filePath(): string {\n return join(this.#shipyardHome, TOKEN_FILE);\n }\n\n #lockPath(): string {\n return `${this.#filePath()}.lock`;\n }\n\n /** Read mtime from disk. Returns -1 if file does not exist. */\n #readMtimeMs(): number {\n try {\n return statSync(this.#filePath()).mtimeMs;\n } catch {\n return -1;\n }\n }\n\n /**\n * Synchronously reload the cache from disk if the file has changed\n * (or if we have never loaded). Uses file mtime to avoid unnecessary reads.\n */\n #loadSync(): void {\n const currentMtime = this.#readMtimeMs();\n if (currentMtime === this.#lastMtimeMs) return;\n\n try {\n if (currentMtime === -1) {\n this.#cache = {};\n this.#lastMtimeMs = currentMtime;\n return;\n }\n const raw = readFileSync(this.#filePath(), 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; shape validated by file ownership (daemon writes exclusively)\n this.#cache = JSON.parse(raw) as TokenMap;\n this.#lastMtimeMs = currentMtime;\n } catch (err: unknown) {\n this.#log({\n event: 'token_store_parse_failed',\n path: this.#filePath(),\n error: err instanceof Error ? err.message : String(err),\n });\n this.#cache = {};\n /** Set mtime so we re-read on next change rather than retrying every call */\n this.#lastMtimeMs = currentMtime;\n }\n }\n\n /** Async mtime check. Returns -1 if file does not exist. */\n async #readMtimeMsAsync(): Promise<number> {\n try {\n return (await stat(this.#filePath())).mtimeMs;\n } catch {\n return -1;\n }\n }\n\n /**\n * Async load for READS — skips the disk read when the file is unchanged\n * (mtime gate). A slightly stale read is acceptable for getters.\n */\n async #load(): Promise<void> {\n const currentMtime = await this.#readMtimeMsAsync();\n if (currentMtime === this.#lastMtimeMs) return;\n await this.#readFromDisk(currentMtime);\n }\n\n /**\n * Unconditional fresh read for the WRITE path (under the cross-process lock).\n * The mtime gate in `#load` is unsafe inside a write critical section: a\n * same-mtime collision between two daemons could skip picking up a peer's\n * just-written token and clobber it. Writes must always read the latest disk\n * state, mirroring the dedicated `readFromDisk` in the other stores.\n */\n async #loadFresh(): Promise<void> {\n await this.#readFromDisk(await this.#readMtimeMsAsync());\n }\n\n async #readFromDisk(currentMtime: number): Promise<void> {\n if (currentMtime === -1) {\n this.#cache = {};\n this.#lastMtimeMs = -1;\n return;\n }\n try {\n const raw = await readFile(this.#filePath(), 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; shape validated by file ownership (daemon writes exclusively)\n this.#cache = JSON.parse(raw) as TokenMap;\n this.#lastMtimeMs = currentMtime;\n } catch (err: unknown) {\n this.#log({\n event: 'token_store_parse_failed',\n path: this.#filePath(),\n error: err instanceof Error ? err.message : String(err),\n });\n this.#cache = {};\n this.#lastMtimeMs = currentMtime;\n }\n }\n\n async #persist(): Promise<void> {\n await atomicWriteFile(this.#filePath(), JSON.stringify(this.#cache, null, 2), {\n mode: 0o600,\n });\n /**\n * Invalidate the mtime gate rather than snapshotting it from a post-write\n * `stat`: on coarse-resolution filesystems a peer's same-second write could\n * share our mtime and be skipped by the next `#load`. Forcing one reload on\n * the next read guarantees we observe concurrent writes.\n */\n this.#lastMtimeMs = -1;\n }\n\n async getToken(serverName: string): Promise<MCPOAuthToken | null> {\n await this.#load();\n return this.#cache[serverName] ?? null;\n }\n\n /**\n * Look up a token by `serverUrl`, scanning across all display-name keys.\n * Use when the caller has the server's URL but its display name may not match\n * how the token was originally stored (see {@link selectTokenByUrl}).\n */\n async getTokenByUrl(serverUrl: string): Promise<MCPOAuthToken | null> {\n await this.#load();\n return selectTokenByUrl(this.#cache, serverUrl, Date.now());\n }\n\n async setToken(serverName: string, token: MCPOAuthToken): Promise<void> {\n await this.#enqueueMutation(() =>\n withFileLock(this.#lockPath(), async () => {\n await this.#loadFresh();\n this.#cache[serverName] = token;\n await this.#persist();\n })\n );\n /** Fire the change callback outside the lock — it may run arbitrarily long work. */\n this.#onChange?.(serverName, token);\n }\n\n async deleteToken(serverName: string): Promise<void> {\n return this.#enqueueMutation(() =>\n withFileLock(this.#lockPath(), async () => {\n await this.#loadFresh();\n delete this.#cache[serverName];\n await this.#persist();\n })\n );\n }\n\n /**\n * Delete every token entry whose `serverUrl` matches, regardless of the\n * display-name key it was stored under. The same credential is saved under\n * sibling casings (`Figma` from claude.ai, `figma` from a CC plugin) that\n * all share one `serverUrl`. Reauth must remove ALL of them: leaving a\n * sibling behind lets {@link MCPTokenStore.getTokenByUrl} resurface a stale\n * refresh_token, which makes the SDK's `auth()` attempt a doomed refresh\n * (server replies 403) instead of opening a fresh browser authorize.\n */\n async deleteTokensByUrl(serverUrl: string): Promise<void> {\n if (!serverUrl) return;\n return this.#enqueueMutation(() =>\n withFileLock(this.#lockPath(), async () => {\n await this.#loadFresh();\n let changed = false;\n for (const [name, token] of Object.entries(this.#cache)) {\n if (token.serverUrl === serverUrl) {\n delete this.#cache[name];\n changed = true;\n }\n }\n if (changed) await this.#persist();\n })\n );\n }\n\n async getAllTokens(): Promise<TokenMap> {\n await this.#load();\n return { ...this.#cache };\n }\n\n getTokenSync(serverName: string): MCPOAuthToken | null {\n this.#loadSync();\n return this.#cache[serverName] ?? null;\n }\n\n isExpired(token: MCPOAuthToken): boolean {\n if (!token.expiresAt) return false;\n return Date.now() >= token.expiresAt;\n }\n\n needsRefresh(token: MCPOAuthToken): boolean {\n if (token.expiresAt === undefined) return false;\n return Date.now() >= token.expiresAt - REFRESH_THRESHOLD_MS;\n }\n}\n","import { execFile as execFileCb } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport { logger } from '../logger.js';\n\nconst execFile = promisify(execFileCb);\n\nexport type AnthropicCredentialsLog = (entry: {\n event: string;\n reason?: string;\n [key: string]: unknown;\n}) => void;\n\nconst defaultLog: AnthropicCredentialsLog = (entry) => logger.debug(entry, entry.event);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nasync function readKeychainEntry(service: string): Promise<string | null> {\n if (process.platform !== 'darwin') return null;\n try {\n const { stdout } = await execFile('security', ['find-generic-password', '-s', service, '-w'], {\n timeout: 5_000,\n });\n const value = stdout.trim();\n return value || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read the OAuth access token from the `Claude Code-credentials` Keychain entry,\n * stored as `claudeAiOauth.accessToken` by `claude setup-token` / `claude auth login`.\n *\n * This is the canonical token for talking to claude.ai-hosted services\n * (e.g. `https://api.anthropic.com/v1/mcp_servers`) on behalf of an OAuth-authed user.\n */\nexport async function readKeychainOAuthToken(\n log: AnthropicCredentialsLog = defaultLog\n): Promise<string | null> {\n if (process.platform !== 'darwin') {\n log({ event: 'anthropic_keychain_read_skipped', reason: 'non_darwin' });\n return null;\n }\n const raw = await readKeychainEntry('Claude Code-credentials');\n if (!raw) {\n log({ event: 'anthropic_keychain_oauth_missing', reason: 'no_credentials_entry' });\n return null;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n log({ event: 'anthropic_keychain_oauth_corrupt', reason: 'json_parse_error' });\n return null;\n }\n if (!isRecord(parsed)) {\n log({ event: 'anthropic_keychain_oauth_corrupt', reason: 'json_parse_error' });\n return null;\n }\n const oauth = parsed.claudeAiOauth;\n if (!isRecord(oauth)) {\n log({ event: 'anthropic_keychain_oauth_missing', reason: 'no_oauth_field' });\n return null;\n }\n const token = oauth.accessToken;\n if (typeof token !== 'string' || token.length === 0) {\n log({ event: 'anthropic_keychain_oauth_missing', reason: 'no_oauth_field' });\n return null;\n }\n return token;\n}\n\n/**\n * Read the managed API key from the `Claude Code` Keychain entry —\n * the value stored by `claude login` for direct Messages API calls\n * (paired with the billing header prefix).\n */\nexport async function readKeychainManagedKey(): Promise<string | null> {\n const value = await readKeychainEntry('Claude Code');\n if (!value || !value.startsWith('sk-')) return null;\n return value;\n}\n","/**\n * Runtime descriptor catalog — knows what runtimes exist, their display\n * names, and how to install them. Auth-shape mapping lives in the\n * sibling `auth-adapters.ts` module (single source of truth keyed by\n * profile id) so this file stays focused on the *runtime* concern.\n */\n\nexport const CLAUDE_CODE_RUNTIME_ID = 'claude-code' as const;\nexport const CODEX_RUNTIME_ID = 'codex' as const;\nexport const CURSOR_RUNTIME_ID = 'cursor' as const;\n\nexport interface RuntimeInstallCommand {\n command: string;\n args: string[];\n}\n\nexport interface RuntimeDescriptor {\n runtimeId: string;\n providerId: string;\n displayName: string;\n buildInstallCommand(platform: NodeJS.Platform): RuntimeInstallCommand | null;\n}\n\nconst CLAUDE_RUNTIME: RuntimeDescriptor = {\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n providerId: 'anthropic',\n displayName: 'Claude Code',\n buildInstallCommand(platform) {\n if (platform === 'win32') {\n return {\n command: 'powershell',\n args: ['-Command', 'irm https://claude.ai/install.ps1 | iex'],\n };\n }\n return {\n command: 'bash',\n args: ['-c', 'curl -fsSL https://claude.ai/install.sh | bash'],\n };\n },\n};\n\nconst CODEX_RUNTIME: RuntimeDescriptor = {\n runtimeId: CODEX_RUNTIME_ID,\n providerId: 'openai',\n displayName: 'Codex',\n buildInstallCommand(platform) {\n return {\n command: platform === 'win32' ? 'npm.cmd' : 'npm',\n args: ['install', '-g', '@openai/codex'],\n };\n },\n};\n\nconst CURSOR_RUNTIME: RuntimeDescriptor = {\n runtimeId: CURSOR_RUNTIME_ID,\n providerId: 'cursor',\n displayName: 'Cursor',\n buildInstallCommand() {\n /** Cursor ships bundled with Shipyard via `@cursor/sdk` — no external install path. */\n return null;\n },\n};\n\nconst RUNTIME_DESCRIPTORS = new Map<string, RuntimeDescriptor>([\n [CLAUDE_RUNTIME.runtimeId, CLAUDE_RUNTIME],\n [CODEX_RUNTIME.runtimeId, CODEX_RUNTIME],\n [CURSOR_RUNTIME.runtimeId, CURSOR_RUNTIME],\n]);\n\nexport function getRuntimeDescriptor(runtimeId: string): RuntimeDescriptor | null {\n return RUNTIME_DESCRIPTORS.get(runtimeId) ?? null;\n}\n\nexport function getRuntimeDisplayName(runtimeId: string): string {\n const known = getRuntimeDescriptor(runtimeId);\n if (known) return known.displayName;\n return runtimeId\n .split(/[-_]/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n}\n\n/**\n * `buildRuntimeAuthMap` is intentionally re-exported via the parent\n * `shared/capabilities/index.ts` barrel rather than here — re-exporting\n * from `./auth-adapters.js` at the bottom of this module would create a\n * circular import (`auth-adapters.ts` imports the runtime-id constants\n * declared above). Callers should import from `../index.js` or from\n * `./auth-adapters.js` directly.\n */\n","import type { MCPServerInfo } from '@shipyard/session';\n\nimport { readKeychainOAuthToken } from '../auth/anthropic-credentials.js';\nimport { CLAUDE_CODE_RUNTIME_ID } from './runtime/catalog.js';\n\ntype Log = (entry: { event: string; [key: string]: unknown }) => void;\n\nconst CLAUDEAI_INTEGRATIONS_URL = 'https://api.anthropic.com/v1/mcp_servers?limit=1000';\nconst ERROR_BODY_MAX_CHARS = 256;\n\n/**\n * After an auth rejection (401/403), the user's Anthropic token is invalid and\n * will stay invalid until they re-authenticate — re-fetching on every ~5-min\n * capability tick just produces a 401 storm (35× in one session in the wild).\n * Suppress the fetch for this window after an auth failure; a successful fetch\n * clears it immediately. Module-level state mirrors the existing per-file caches\n * in `mcp-servers.ts`; reset via `__resetClaudeAiIntegrationsBackoffForTesting`.\n */\nconst AUTH_BACKOFF_MS = 30 * 60_000;\nlet authBackoffUntil = 0;\n\n/** Test-only seam to reset the auth backoff between cases. */\nexport function __resetClaudeAiIntegrationsBackoffForTesting(): void {\n authBackoffUntil = 0;\n}\n\ntype FetchFailureClass = 'http_4xx' | 'http_5xx' | 'http_other' | 'network' | 'timeout' | 'parse';\n\n/**\n * Minimal shape we expect from the Anthropic MCP servers API response.\n * Hand-rolled instead of Zod to keep best-effort parsing lightweight.\n */\nexport function parseClaudeAiServers(\n data: unknown,\n log?: Log\n): Array<{ name: string; url: string; id?: string }> {\n if (typeof data !== 'object' || data === null) return [];\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; manually validated below\n const obj = data as Record<string, unknown>;\n if (!Array.isArray(obj.data)) return [];\n const results: Array<{ name: string; url: string; id?: string }> = [];\n let legacyNameCount = 0;\n for (const entry of obj.data) {\n const parsed = parseServerRecord(entry);\n if (!parsed) continue;\n if (parsed.legacy) legacyNameCount += 1;\n results.push(parsed.entry);\n }\n if (legacyNameCount > 0 && log) {\n log({\n event: 'claudeai_integrations_legacy_name_fallback',\n count: legacyNameCount,\n });\n }\n return results;\n}\n\ninterface ParsedServerRecord {\n entry: { name: string; url: string; id?: string };\n /** True when the name came from the legacy `name` field, not `display_name`. */\n legacy: boolean;\n}\n\n/**\n * Pure: extract one `{name, url, id?}` entry from a raw API record, or null when\n * it lacks a usable url + name. `display_name` is preferred; the legacy `name`\n * field is the forward-compat fallback (also used by synthetic test fixtures).\n * The gateway id (`mcpsrv_…`) is kept when present — it routes the connector\n * through `mcp-proxy.anthropic.com/v1/mcp/{id}`; absent on legacy records, which\n * then fall back to plain DCR.\n */\nfunction parseServerRecord(entry: unknown): ParsedServerRecord | null {\n if (typeof entry !== 'object' || entry === null) return null;\n // eslint-disable-next-line no-restricted-syntax -- narrowing unknown entry fields\n const rec = entry as Record<string, unknown>;\n if (typeof rec.url !== 'string') return null;\n const id = typeof rec.id === 'string' ? rec.id : undefined;\n if (typeof rec.display_name === 'string') {\n return { entry: makeServerEntry(rec.display_name, rec.url, id), legacy: false };\n }\n if (typeof rec.name === 'string') {\n return { entry: makeServerEntry(rec.name, rec.url, id), legacy: true };\n }\n return null;\n}\n\n/** Build a server entry, omitting `id` entirely when absent (no `id: undefined` key). */\nfunction makeServerEntry(\n name: string,\n url: string,\n id: string | undefined\n): { name: string; url: string; id?: string } {\n return id ? { name, url, id } : { name, url };\n}\n\nfunction classifyHttpStatus(status: number): FetchFailureClass {\n if (status >= 400 && status < 500) return 'http_4xx';\n if (status >= 500 && status < 600) return 'http_5xx';\n return 'http_other';\n}\n\nfunction classifyException(err: unknown): FetchFailureClass {\n if (err instanceof Error) {\n if (err.name === 'AbortError') return 'timeout';\n if (err.name === 'SyntaxError') return 'parse';\n }\n return 'network';\n}\n\n/**\n * Best-effort tail-readers for the failure body. We do NOT log Authorization\n * headers or other request metadata — the URL is a stable public endpoint and\n * the body is the model's own error envelope, so neither carries the user's\n * OAuth token. Truncated to bound log payload size.\n */\nasync function readErrorBody(response: Response): Promise<string | null> {\n try {\n const text = await response.text();\n if (text.length === 0) return null;\n return text.length <= ERROR_BODY_MAX_CHARS ? text : text.slice(0, ERROR_BODY_MAX_CHARS);\n } catch {\n return null;\n }\n}\n\n/**\n * Fetch MCP server integrations from the user's Claude.ai account.\n * Best-effort: returns [] on any failure.\n */\nexport async function fetchClaudeAiIntegrations(log: Log): Promise<MCPServerInfo[]> {\n const url = CLAUDEAI_INTEGRATIONS_URL;\n if (Date.now() < authBackoffUntil) {\n /** Recent auth failure — skip silently until the backoff elapses or auth is re-established. */\n return [];\n }\n try {\n const token = await readKeychainOAuthToken(log);\n if (!token) {\n log({ event: 'claudeai_integrations_skipped', reason: 'no_oauth_token' });\n return [];\n }\n\n const controller = new AbortController();\n /**\n * 5s cap on the claude.ai Connectors fetch. Anthropic's API normally\n * responds in <500ms; 10s was generous slack that singlehandedly added\n * up to 10s of boot stall when the API hung. 5s is the same bound used\n * by the sibling auth-status timeout. See issue #3267.\n */\n const timeout = setTimeout(() => controller.abort(), 5_000);\n\n try {\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'anthropic-version': '2023-06-01',\n 'anthropic-beta': 'mcp-servers-2025-12-04',\n },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await readErrorBody(response);\n log({\n event: 'claudeai_integrations_fetch_failed',\n url,\n status: response.status,\n errorClass: classifyHttpStatus(response.status),\n errorBody,\n });\n if (response.status === 401 || response.status === 403) {\n authBackoffUntil = Date.now() + AUTH_BACKOFF_MS;\n log({\n event: 'claudeai_integrations_auth_backoff',\n status: response.status,\n backoffMs: AUTH_BACKOFF_MS,\n });\n }\n return [];\n }\n\n /** Success — token is valid again; clear any prior auth backoff. */\n authBackoffUntil = 0;\n const body: unknown = await response.json();\n const servers = parseClaudeAiServers(body, log);\n\n return servers.map((s) => ({\n name: s.name,\n type: 'http' as const,\n runtimeId: CLAUDE_CODE_RUNTIME_ID,\n url: s.url,\n enabled: true,\n source: 'claudeai' as const,\n authStatus: 'unknown' as const,\n /** Gateway id — drives the `mcp-proxy.anthropic.com/v1/mcp/{id}` route. */\n ...(s.id ? { id: s.id } : {}),\n }));\n } finally {\n clearTimeout(timeout);\n }\n } catch (err: unknown) {\n log({\n event: 'claudeai_integrations_fetch_failed',\n url,\n status: null,\n errorClass: classifyException(err),\n errorBody: null,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n}\n"],"mappings":"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","names":["readFile","stat","homedir","join","readFile","join","join","readFile","execFileCb","promisify","execFile","promisify","execFileCb","stat","readFile","join","homedir","logger"]}