dynmcp 0.4.1 → 0.6.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../package.json","../src/proxy/index.ts","../src/config/schema.ts","../src/config/loader.ts","../src/config/env-sources.ts","../src/config/interpolate.ts","../src/config/json-schema.ts","../src/proxy/orchestrator.ts","../src/proxy/capability-aggregator.ts","../src/proxy/lazy-registry.ts","../src/proxy/notification-forwarder.ts","../src/proxy/prompt-router.ts","../src/proxy/resource-router.ts","../src/proxy/tool-catalog.ts","../src/proxy/upstream-client.ts","../src/proxy/upstream-registry.ts","../src/proxy/server.ts","../src/proxy/transport-factory.ts","../src/index.ts"],"sourcesContent":["import process from \"node:process\";\nimport { Command } from \"commander\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport figlet from \"figlet\";\nimport chalk from \"chalk\";\nimport { startProxy, startProxyFromConfig } from \"./proxy/index.js\";\n\nconst cliBanner = chalk.bold.magentaBright(\n figlet.textSync(\"DYNAMIC MCP\", {\n font: \"Sub-Zero\",\n horizontalLayout: \"fitted\",\n verticalLayout: \"fitted\",\n }),\n);\n\nexport const cli = new Command(packageJson.name)\n .description(packageJson.description)\n .version(packageJson.version)\n .addHelpText(\"beforeAll\", cliBanner)\n .addHelpText(\n \"after\",\n \"\\nExamples:\\n\" +\n \" dynmcp -- npx -y chrome-devtools-mcp@latest\\n\" +\n \" dynmcp --config ./mcp.json\\n\",\n )\n .option(\"-c, --config <path>\", \"Path to config file (JSON or YAML)\")\n .option(\"-e, --env <path>\", \"Path to a .env file for environment variable interpolation\")\n .allowExcessArguments(true)\n .passThroughOptions(true)\n .action(async (_options, cmd) => {\n const separatorIndex = process.argv.indexOf(\"--\");\n const configPath = cmd.opts().config as string | undefined;\n const envFilePath = cmd.opts().env as string | undefined;\n\n if (separatorIndex !== -1) {\n const [command, ...args] = process.argv.slice(separatorIndex + 1);\n\n if (command === undefined) {\n process.stderr.write(\n \"dynmcp: no upstream command provided after --.\\n\" +\n \"Usage: dynmcp -- <command> [args...]\\n\",\n );\n process.exit(1);\n }\n\n try {\n await startProxy(command, args);\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n return;\n }\n\n try {\n await startProxyFromConfig({ configPath, envFilePath });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n });\n","{\n \"name\": \"dynmcp\",\n \"version\": \"0.4.1\",\n \"description\": \"Dynamic MCP context management tool for AI MCP-enabled agents and clients.\",\n \"author\": \"Brandon Burrus <brandon@burrus.io>\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"homepage\": \"https://dynamicmcp.tools\",\n \"keywords\": [\n \"mcp\",\n \"model-context-protocol\",\n \"ai\",\n \"agent\",\n \"proxy\",\n \"dynamic\",\n \"discovery\",\n \"tools\",\n \"llm\",\n \"cli\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/brandonburrus/dynamic-discovery-mcp.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/brandonburrus/dynamic-discovery-mcp/issues\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"dynmcp\": \"./dist/index.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"generate:schema\": \"tsx scripts/generate-schema.ts\",\n \"build\": \"tsup\",\n \"dev\": \"tsx src/index.ts\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"biome lint .\",\n \"format\": \"biome format --write .\",\n \"check\": \"biome check --write .\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"prepare\": \"husky\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.29.0\",\n \"boxen\": \"^8.0.1\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^14.0.3\",\n \"dotenv\": \"^17.4.2\",\n \"enquirer\": \"^2.4.1\",\n \"fastmcp\": \"^4.0.1\",\n \"figlet\": \"^1.11.0\",\n \"figures\": \"^6.1.0\",\n \"yaml\": \"^2.9.0\",\n \"zod\": \"^4.4.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.4.15\",\n \"@commitlint/cli\": \"^21.0.1\",\n \"@commitlint/config-conventional\": \"^21.0.1\",\n \"@types/node\": \"^25.9.0\",\n \"@vitest/coverage-v8\": \"^4.1.6\",\n \"husky\": \"^9.1.7\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.22.2\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.6\"\n }\n}\n","import process from \"node:process\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { loadConfig } from \"../config/index.js\";\nimport { type EagerMcpConfig, type LazyMcpConfig, Orchestrator } from \"./orchestrator.js\";\nimport { ProxyServer } from \"./server.js\";\nimport { createTransport } from \"./transport-factory.js\";\n\nconst SINGLE_MCP_NAME = \"__default__\";\n\nexport async function startProxy(command: string, args: string[]): Promise<void> {\n const transport = new StdioClientTransport({ command, args });\n const eagerMcps = new Map<string, EagerMcpConfig>([[SINGLE_MCP_NAME, { transport }]]);\n\n const orchestrator = buildOrchestrator({\n eagerMcps,\n namespaced: false,\n transportErrorPrefix: () => \"Upstream MCP\",\n });\n\n await runProxy(orchestrator);\n}\n\nexport interface StartProxyFromConfigOptions {\n configPath?: string;\n envFilePath?: string;\n}\n\nexport async function startProxyFromConfig(\n options: StartProxyFromConfigOptions = {},\n): Promise<void> {\n const config = loadConfig(options);\n\n // Partition by `description` presence: entries with a description become lazy\n // upstreams (deferred connection, dynamic discovery enabled); the rest are eager.\n // Order within each partition preserves config-file order.\n const eagerMcps = new Map<string, EagerMcpConfig>();\n const lazyMcps = new Map<string, LazyMcpConfig>();\n for (const [name, entry] of Object.entries(config.mcp)) {\n const transport = createTransport(entry);\n if (entry.description !== undefined) {\n lazyMcps.set(name, { transport, description: entry.description });\n } else {\n eagerMcps.set(name, { transport });\n }\n }\n\n const orchestrator = buildOrchestrator({\n eagerMcps,\n lazyMcps,\n namespaced: true,\n transportErrorPrefix: mcpName => `Upstream MCP \"${mcpName}\"`,\n });\n\n await runProxy(orchestrator);\n}\n\ntype BuildOrchestratorParams = {\n eagerMcps: Map<string, EagerMcpConfig>;\n lazyMcps?: Map<string, LazyMcpConfig>;\n namespaced: boolean;\n transportErrorPrefix: (mcpName: string) => string;\n};\n\n// Forward declaration so buildOrchestrator can reference the shutdown closure constructed\n// inside runProxy. Each invocation of runProxy installs its own shutdown function on this\n// holder before the orchestrator's transport-error callbacks can fire.\ntype ShutdownHolder = { shutdown: ((code: number) => void) | null };\n\nconst activeShutdown: ShutdownHolder = { shutdown: null };\n\nfunction buildOrchestrator(params: BuildOrchestratorParams): Orchestrator {\n return new Orchestrator({\n eagerMcps: params.eagerMcps,\n lazyMcps: params.lazyMcps,\n namespaced: params.namespaced,\n onTransportError: (mcpName: string, error: Error) => {\n process.stderr.write(\n `${params.transportErrorPrefix(mcpName)} transport error: ${error.message}\\n`,\n );\n activeShutdown.shutdown?.(1);\n },\n });\n}\n\nasync function runProxy(orchestrator: Orchestrator): Promise<void> {\n let isShuttingDown = false;\n\n const shutdown = (exitCode: number): void => {\n if (isShuttingDown) return;\n isShuttingDown = true;\n\n orchestrator\n .disconnectAll()\n .catch((error: unknown) => {\n process.stderr.write(\n `dynmcp: error during disconnect: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n })\n .finally(() => process.exit(exitCode));\n };\n\n activeShutdown.shutdown = shutdown;\n\n try {\n await orchestrator.connect();\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n return;\n }\n\n const proxyServer = new ProxyServer({\n catalog: () => orchestrator.catalog,\n capabilities: orchestrator.capabilities,\n callTool: (name, input, options) => orchestrator.callTool(name, input, options),\n resources:\n orchestrator.capabilities.resources !== undefined\n ? {\n listResources: () => orchestrator.listResources(),\n listResourceTemplates: () => orchestrator.listResourceTemplates(),\n readResource: (uri, options) => orchestrator.readResource(uri, options),\n subscribeResource: (uri, options) => orchestrator.subscribeResource(uri, options),\n unsubscribeResource: (uri, options) => orchestrator.unsubscribeResource(uri, options),\n }\n : undefined,\n prompts:\n orchestrator.capabilities.prompts !== undefined\n ? {\n listPrompts: () => orchestrator.listPrompts(),\n getPrompt: (name, args, options) => orchestrator.getPrompt(name, args, options),\n }\n : undefined,\n complete:\n orchestrator.capabilities.completions !== undefined\n ? (params, options) => orchestrator.complete(params, options)\n : undefined,\n setLoggingLevel:\n orchestrator.capabilities.logging !== undefined\n ? (level, options) => orchestrator.setLoggingLevel(level, options)\n : undefined,\n onRootsListChanged: () => orchestrator.broadcastRootsListChanged(),\n // Only register the `load_mcp` meta-tool when dynamic discovery is enabled —\n // i.e. when the config declared at least one lazy upstream MCP.\n loadMcp: orchestrator.hasDynamicDiscovery\n ? mcpName => orchestrator.loadMcp(mcpName)\n : undefined,\n });\n\n orchestrator.setNotificationHandlers({\n onToolsListChanged: () => proxyServer.sendToolListChanged(),\n onResourcesListChanged: () => proxyServer.sendResourceListChanged(),\n onResourceUpdated: params => proxyServer.sendResourceUpdated(params),\n onPromptsListChanged: () => proxyServer.sendPromptListChanged(),\n onLogMessage: params => proxyServer.sendLoggingMessage(params),\n });\n\n orchestrator.setServerRequestForwarders({\n onCreateMessage: (params, options) => proxyServer.forwardCreateMessage(params, options),\n onElicitInput: (params, options) => proxyServer.forwardElicitInput(params, options),\n onListRoots: (params, options) => proxyServer.forwardListRoots(params, options),\n });\n\n process.on(\"SIGINT\", () => shutdown(0));\n process.on(\"SIGTERM\", () => shutdown(0));\n process.stdin.on(\"end\", () => shutdown(0));\n process.stdin.on(\"close\", () => shutdown(0));\n\n try {\n await proxyServer.start();\n } catch (error) {\n shutdown(1);\n throw error;\n }\n}\n","import { z } from \"zod\";\n\nexport const MCP_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;\n\nconst mcpName = z.string().regex(MCP_NAME_PATTERN);\n\nexport const envModeSchema = z\n .enum([\"enable\", \"dotenv\", \"process\", \"disable\"])\n .describe(\n 'Controls environment variable interpolation in config values. \"enable\" (default) merges .env and process.env (.env wins). \"dotenv\" loads .env only. \"process\" uses process.env only. \"disable\" turns interpolation off.',\n );\n\nexport type EnvMode = z.infer<typeof envModeSchema>;\n\n/**\n * Optional per-entry description. When present (and non-whitespace), the MCP becomes\n * a lazy upstream and the proxy enables dynamic discovery. The string is shown to the\n * agent in the `<mcp_servers>` block of `discover_tool`'s description so the agent\n * can decide whether to invoke `load_mcp` for it. The `.refine` runs after env-var\n * interpolation, so values that resolve to whitespace-only are also rejected.\n */\nconst description = z\n .string()\n .min(1, { message: \"description must be a non-empty string\" })\n .refine(value => value.trim().length > 0, {\n message: \"description must not be whitespace-only\",\n })\n .optional();\n\nconst stdioTransport = z\n .object({\n transport: z.literal(\"stdio\"),\n description,\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n })\n .strict();\n\nconst httpUrl = z\n .string()\n .url()\n .refine(u => u.startsWith(\"http://\") || u.startsWith(\"https://\"), {\n message: \"URL must use http:// or https:// scheme\",\n });\n\nconst streamableHttpTransport = z\n .object({\n transport: z.literal(\"streamable-http\"),\n description,\n url: httpUrl,\n headers: z.record(z.string(), z.string()).optional(),\n })\n .strict();\n\nconst sseTransport = z\n .object({\n transport: z.literal(\"sse\"),\n description,\n url: httpUrl,\n headers: z.record(z.string(), z.string()).optional(),\n })\n .strict();\n\nconst transportConfig = z.discriminatedUnion(\"transport\", [\n stdioTransport,\n streamableHttpTransport,\n sseTransport,\n]);\n\nexport const mcpConfigSchema = z.object({\n env: envModeSchema.optional(),\n mcp: z\n .record(mcpName, transportConfig)\n .refine(obj => Object.keys(obj).length > 0, { message: \"At least one MCP must be configured\" }),\n});\n\nexport type McpConfig = z.infer<typeof mcpConfigSchema>;\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { parse as parseYaml } from \"yaml\";\nimport { loadEnv } from \"./env-sources.js\";\nimport { interpolateConfig } from \"./interpolate.js\";\nimport { type EnvMode, type McpConfig, mcpConfigSchema } from \"./schema.js\";\n\nconst AUTO_DISCOVER_NAMES = [\"mcp.json\", \".mcp.json\"] as const;\nconst DEFAULT_ENV_MODE: EnvMode = \"enable\";\nconst VALID_ENV_MODES: readonly EnvMode[] = [\"enable\", \"dotenv\", \"process\", \"disable\"];\n\nexport interface LoadConfigOptions {\n /** Path to the config file. If omitted, auto-discovers `mcp.json` then `.mcp.json` in cwd. */\n configPath?: string;\n /** Path to a custom `.env` file (from the `--env` / `-e` CLI flag). */\n envFilePath?: string;\n}\n\n/**\n * Resolves the config file path without loading or parsing it.\n *\n * @param explicitPath - If provided, resolves this path directly.\n * @returns The absolute path to the config file.\n * @throws If no config file is found at the explicit path or via auto-discovery.\n */\nexport function resolveConfigPath(explicitPath?: string): string {\n if (explicitPath) {\n const resolved = resolve(explicitPath);\n if (!existsSync(resolved)) {\n throw new Error(`Config file not found: ${resolved}`);\n }\n return resolved;\n }\n\n const cwd = process.cwd();\n for (const name of AUTO_DISCOVER_NAMES) {\n const candidate = resolve(cwd, name);\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n const searched = AUTO_DISCOVER_NAMES.map(n => resolve(cwd, n)).join(\", \");\n throw new Error(`No config file found. Searched: ${searched}`);\n}\n\n/**\n * Loads, parses, interpolates, and validates the dynmcp config file.\n *\n * Flow: resolve path → read file → parse JSON/YAML → read env mode →\n * load env sources → interpolate `${VAR}` references → Zod validate.\n *\n * @param options - Config path and optional custom `.env` file path.\n * @returns The validated config object with all interpolations resolved.\n * @throws On missing file, parse errors, missing env vars, or schema validation failures.\n */\nexport function loadConfig(options: LoadConfigOptions = {}): McpConfig {\n const { configPath, envFilePath } = options;\n\n const resolvedPath = resolveConfigPath(configPath);\n const raw = readFileSync(resolvedPath, \"utf-8\");\n\n let content: unknown;\n try {\n content = isYamlFile(resolvedPath) ? parseYaml(raw) : JSON.parse(raw);\n } catch (parseError) {\n const message = parseError instanceof Error ? parseError.message : String(parseError);\n throw new Error(`Failed to parse config file (${resolvedPath}): ${message}`);\n }\n\n const envMode = readEnvMode(content);\n const loadedEnv = loadEnv({ mode: envMode, envFilePath });\n\n const interpolated = loadedEnv.interpolationEnabled\n ? interpolateConfig(content, loadedEnv.variables)\n : content;\n\n const result = mcpConfigSchema.safeParse(interpolated);\n if (!result.success) {\n const formatted = result.error.issues\n .map(issue => ` - ${issue.path.join(\".\")}: ${issue.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid config file (${resolvedPath}):\\n${formatted}`);\n }\n\n return result.data;\n}\n\n/**\n * Reads the top-level `env` field from raw parsed config content. This runs\n * before Zod validation so we can resolve env vars before validating types.\n *\n * If the field is missing, the default mode is returned. If it is present but\n * not a recognized value, the default is returned so that Zod can surface a\n * specific validation error later.\n */\nfunction readEnvMode(content: unknown): EnvMode {\n if (content === null || typeof content !== \"object\" || Array.isArray(content)) {\n return DEFAULT_ENV_MODE;\n }\n const value = (content as Record<string, unknown>).env;\n if (value === undefined) return DEFAULT_ENV_MODE;\n if (typeof value === \"string\" && (VALID_ENV_MODES as readonly string[]).includes(value)) {\n return value as EnvMode;\n }\n return DEFAULT_ENV_MODE;\n}\n\nfunction isYamlFile(filePath: string): boolean {\n return filePath.endsWith(\".yml\") || filePath.endsWith(\".yaml\");\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport process from \"node:process\";\nimport dotenv from \"dotenv\";\nimport type { EnvMode } from \"./schema.js\";\n\nconst DEFAULT_DOTENV_FILENAME = \".env\";\n\nexport interface LoadEnvOptions {\n /** Env interpolation mode (from config file top-level `env` field). */\n mode: EnvMode;\n /** Custom `.env` path from the `--env` / `-e` CLI flag. When provided, the file must exist. */\n envFilePath?: string;\n /** Override for cwd (testability). Defaults to `process.cwd()`. */\n cwd?: string;\n /** Override for process.env (testability). Defaults to `process.env`. */\n processEnv?: NodeJS.ProcessEnv;\n}\n\nexport interface LoadedEnv {\n /** Merged variable map ready for interpolation. */\n variables: Record<string, string>;\n /** Whether interpolation should run at all. False only when mode is \"disable\". */\n interpolationEnabled: boolean;\n}\n\n/**\n * Resolves the environment variable map used for config interpolation.\n *\n * Precedence rules:\n * - mode \"enable\": load .env + process.env, .env wins for duplicates.\n * - mode \"dotenv\": load .env only; process.env is ignored.\n * - mode \"process\": process.env only; no .env file is loaded.\n * - mode \"disable\": no sources; interpolation is turned off.\n *\n * The `--env` flag is incompatible with \"disable\" and \"process\" modes and is\n * rejected at startup as an incoherent combination.\n *\n * @throws If `--env` is combined with an incompatible mode.\n * @throws If an explicit `--env` path does not exist or cannot be parsed.\n */\nexport function loadEnv(options: LoadEnvOptions): LoadedEnv {\n const { mode, envFilePath, cwd = process.cwd(), processEnv = process.env } = options;\n\n if (envFilePath !== undefined && (mode === \"disable\" || mode === \"process\")) {\n throw new Error(\n `--env flag is incompatible with env mode \"${mode}\". --env requires env mode \"enable\" or \"dotenv\".`,\n );\n }\n\n if (mode === \"disable\") {\n return { variables: {}, interpolationEnabled: false };\n }\n\n const dotenvVars = mode === \"process\" ? {} : readDotenvFile(envFilePath, cwd);\n const processVars = mode === \"dotenv\" ? {} : filterDefined(processEnv);\n\n // For \"enable\" mode, .env wins (later spread overrides earlier).\n // For \"process\" and \"dotenv\" modes only one source is non-empty, so order is moot.\n const variables = { ...processVars, ...dotenvVars };\n\n return { variables, interpolationEnabled: true };\n}\n\nfunction readDotenvFile(envFilePath: string | undefined, cwd: string): Record<string, string> {\n const isExplicit = envFilePath !== undefined;\n const resolvedPath = isExplicit\n ? resolve(envFilePath as string)\n : resolve(cwd, DEFAULT_DOTENV_FILENAME);\n\n if (!existsSync(resolvedPath)) {\n if (isExplicit) {\n throw new Error(`.env file not found: ${resolvedPath}`);\n }\n // Soft-fail: a missing default .env is not an error.\n return {};\n }\n\n let raw: string;\n try {\n raw = readFileSync(resolvedPath, \"utf-8\");\n } catch (readError) {\n const message = readError instanceof Error ? readError.message : String(readError);\n throw new Error(`Failed to read .env file (${resolvedPath}): ${message}`);\n }\n\n try {\n return dotenv.parse(raw);\n } catch (parseError) {\n const message = parseError instanceof Error ? parseError.message : String(parseError);\n throw new Error(`Failed to parse .env file (${resolvedPath}): ${message}`);\n }\n}\n\nfunction filterDefined(env: NodeJS.ProcessEnv): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n","/**\n * Environment variable interpolation for dynmcp config files.\n *\n * Runs after JSON/YAML parsing but before Zod validation, so the validated\n * config contains only fully-resolved string values.\n *\n * Supported syntax (per SPEC.md \"Environment Variable Interpolation\"):\n * - `${VAR}` substitute the value of VAR; missing → error\n * - `${VAR:-default}` substitute VAR, or `default` if VAR is unset or empty\n * - `$${...}` escape — resolves to the literal `${...}`\n *\n * Interpolation applies only to leaf string values reached through the `mcp`\n * subtree. The top-level `$schema` and `env` fields are passed through verbatim.\n */\n\nconst TOP_LEVEL_PASSTHROUGH_KEYS = new Set([\"$schema\", \"env\"]);\n\nexport class MissingEnvVarsError extends Error {\n constructor(public readonly missingVars: readonly string[]) {\n const list = missingVars.join(\", \");\n const plural = missingVars.length === 1 ? \"\" : \"s\";\n super(`Missing required environment variable${plural}: ${list}`);\n this.name = \"MissingEnvVarsError\";\n }\n}\n\n/**\n * Walks a parsed config object and substitutes `${VAR}` references in all leaf\n * string values. Top-level `$schema` and `env` keys are not interpolated.\n *\n * @param config - The parsed (but unvalidated) config object.\n * @param env - The resolved environment variable map (already merged per env mode).\n * @returns A structurally identical config with all string leaves interpolated.\n * @throws {MissingEnvVarsError} If any `${VAR}` reference has no default and no value in env.\n */\nexport function interpolateConfig(config: unknown, env: Record<string, string>): unknown {\n if (config === null || typeof config !== \"object\" || Array.isArray(config)) {\n return config;\n }\n\n const missing: string[] = [];\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(config as Record<string, unknown>)) {\n if (TOP_LEVEL_PASSTHROUGH_KEYS.has(key)) {\n result[key] = value;\n } else {\n result[key] = walkNode(value, env, missing);\n }\n }\n\n if (missing.length > 0) {\n const unique = Array.from(new Set(missing)).sort();\n throw new MissingEnvVarsError(unique);\n }\n\n return result;\n}\n\nfunction walkNode(node: unknown, env: Record<string, string>, missing: string[]): unknown {\n if (typeof node === \"string\") {\n return interpolateString(node, env, missing);\n }\n if (Array.isArray(node)) {\n return node.map(item => walkNode(item, env, missing));\n }\n if (node !== null && typeof node === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node as Record<string, unknown>)) {\n result[key] = walkNode(value, env, missing);\n }\n return result;\n }\n return node;\n}\n\nfunction interpolateString(value: string, env: Record<string, string>, missing: string[]): string {\n let result = \"\";\n let i = 0;\n const len = value.length;\n\n while (i < len) {\n const ch = value[i];\n\n if (ch === \"$\" && value[i + 1] === \"$\" && value[i + 2] === \"{\") {\n // Escape: $${...} -> literal ${...} (strip one leading $)\n const close = value.indexOf(\"}\", i + 3);\n if (close === -1) {\n // Unclosed escape; treat the leading $ as literal and advance one char\n result += ch;\n i += 1;\n continue;\n }\n result += value.substring(i + 1, close + 1);\n i = close + 1;\n continue;\n }\n\n if (ch === \"$\" && value[i + 1] === \"{\") {\n const close = value.indexOf(\"}\", i + 2);\n if (close === -1) {\n // Unclosed expression; emit the rest of the string literally\n result += value.substring(i);\n break;\n }\n const expr = value.substring(i + 2, close);\n const { name, defaultValue } = parseExpr(expr);\n const resolved = env[name];\n const hasValue = resolved !== undefined && resolved !== \"\";\n\n if (hasValue) {\n result += resolved;\n } else if (defaultValue !== undefined) {\n result += defaultValue;\n } else if (resolved !== undefined) {\n // Defined but empty string and no default — treat as the empty string.\n // Per spec: ${VAR} without default fails only when VAR is *undefined*.\n result += \"\";\n } else {\n missing.push(name);\n }\n i = close + 1;\n continue;\n }\n\n result += ch;\n i += 1;\n }\n\n return result;\n}\n\nfunction parseExpr(expr: string): { name: string; defaultValue: string | undefined } {\n const sep = expr.indexOf(\":-\");\n if (sep === -1) {\n return { name: expr, defaultValue: undefined };\n }\n return {\n name: expr.substring(0, sep),\n defaultValue: expr.substring(sep + 2),\n };\n}\n","import { z } from \"zod\";\nimport { mcpConfigSchema } from \"./schema.js\";\n\nexport const MCP_CONFIG_SCHEMA_ID = \"https://dynamicmcp.tools/config.json\";\nexport const MCP_CONFIG_SCHEMA_DRAFT = \"http://json-schema.org/draft-07/schema#\";\n\n/**\n * Generates the JSON Schema for the dynmcp config file from the runtime Zod schema.\n *\n * The schema is targeted at JSON Schema draft-07 for the broadest editor support\n * (VS Code, JetBrains, and the JSON Schema Store all consume draft-07 reliably).\n *\n * @returns A JSON Schema document describing the dynmcp config file format.\n */\nexport function generateMcpConfigJsonSchema(): Record<string, unknown> {\n const generated = z.toJSONSchema(mcpConfigSchema, {\n target: \"draft-7\",\n }) as Record<string, unknown>;\n\n const properties = (generated.properties ?? {}) as Record<string, unknown>;\n const mcpProperty = (properties.mcp ?? {}) as Record<string, unknown>;\n\n return {\n $schema: MCP_CONFIG_SCHEMA_DRAFT,\n $id: MCP_CONFIG_SCHEMA_ID,\n title: \"dynmcp config\",\n description:\n \"Configuration file for dynmcp. Declares the set of upstream MCPs to proxy through dynamic-discovery-mcp.\",\n ...generated,\n properties: {\n ...properties,\n $schema: {\n type: \"string\",\n description: \"URL of the JSON Schema for editor validation.\",\n },\n mcp: {\n ...mcpProperty,\n minProperties: 1,\n description:\n \"Map of upstream MCPs to proxy, keyed by MCP name. Each name becomes the namespace prefix for that MCP's tools.\",\n },\n },\n };\n}\n","import process from \"node:process\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type {\n CallToolResult,\n CompleteRequest,\n CompleteResult,\n CreateMessageRequest,\n CreateMessageResult,\n ElicitRequest,\n ElicitResult,\n GetPromptResult,\n ListRootsRequest,\n ListRootsResult,\n LoggingLevel,\n Prompt,\n ReadResourceResult,\n Resource,\n ResourceTemplate,\n ServerCapabilities,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { aggregateCapabilities } from \"./capability-aggregator.js\";\nimport { LazyRegistry } from \"./lazy-registry.js\";\nimport { NotificationForwarder, type HostNotificationHandlers } from \"./notification-forwarder.js\";\nimport { PromptRouter } from \"./prompt-router.js\";\nimport { ResourceRouter } from \"./resource-router.js\";\nimport { ToolCatalog } from \"./tool-catalog.js\";\nimport type { UpstreamCallOptions, UpstreamClient, UpstreamTool } from \"./upstream-client.js\";\nimport { UpstreamRegistry, type UpstreamConfig } from \"./upstream-registry.js\";\n\nexport type CallOptions = UpstreamCallOptions;\n\nexport type EagerMcpConfig = { transport: Transport };\nexport type LazyMcpConfig = { transport: Transport; description: string };\n\nexport type OrchestratorConfig = {\n /**\n * Upstream MCPs to connect eagerly at startup. In single-MCP (`--`) mode this must\n * contain exactly one entry and `namespaced` must be false.\n */\n eagerMcps: Map<string, EagerMcpConfig>;\n /**\n * Optional lazy upstream MCPs — those declared with a `description` field. Connection\n * is deferred until `loadMcp(name)` is called. The presence of any lazy entry enables\n * dynamic discovery (see SPEC.md § \"Dynamic Discovery\"). Must be empty in single-MCP\n * mode.\n *\n * The iteration order is preserved (config-file order) and is also used for router\n * priority alongside the eager entries — eager names come first, then lazy names, all\n * in their original config-file order.\n */\n lazyMcps?: Map<string, LazyMcpConfig>;\n /**\n * When true (config-file mode), tools are exposed as `<mcpName>/<toolName>` and routed\n * by splitting on the first `/`. When false (single-MCP `--` mode), tools are exposed\n * as bare names and routed to the sole upstream client.\n */\n namespaced: boolean;\n onTransportError?: (mcpName: string, error: Error) => void;\n};\n\n/**\n * Maximum consecutive failed `load_mcp` attempts per lazy MCP before the entry is\n * evicted from {@link LazyRegistry}. Once evicted, the agent receives \"unknown\n * server\" responses on subsequent calls and the entry vanishes from the\n * `<mcp_servers>` block. Three strikes is a balance: transient network or\n * startup hiccups are tolerated, but a permanently broken upstream stops burning\n * agent context forever.\n */\nexport const MAX_LOAD_ATTEMPTS = 3;\n\n/**\n * Structured response returned by {@link Orchestrator.loadMcp}. Mirrors the schema\n * documented in SPEC.md for `load_mcp`'s output. Tool schemas are deliberately omitted\n * — `discover_tool` still owns the schema-retrieval surface; this listing is the\n * \"what's in here\" overview that lets the agent navigate post-load.\n */\nexport type LoadMcpResult = {\n mcp_name: string;\n tools: Array<{ name: string; description: string }>;\n resources: Array<{\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n }>;\n resource_templates: Array<{\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n }>;\n prompts: Array<{\n name: string;\n description?: string;\n arguments?: Prompt[\"arguments\"];\n }>;\n};\n\nexport type OrchestratorNotificationHandlers = HostNotificationHandlers;\n\n/**\n * Forwarders for upstream-initiated requests. The Orchestrator wires each upstream\n * client's incoming request handlers to call into these so the proxy can relay the\n * request to the host. `signal` is the upstream's request-abort signal — passing it\n * through to the host call propagates cancellation if the upstream cancels.\n */\nexport type OrchestratorServerRequestForwarders = {\n onCreateMessage?: (\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<CreateMessageResult>;\n onElicitInput?: (\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ElicitResult>;\n onListRoots?: (\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ListRootsResult>;\n};\n\n/**\n * Composition root for the proxy hub. Composes {@link UpstreamRegistry} (lifecycle),\n * {@link NotificationForwarder} (upstream→host notification translation), and the\n * routers/catalogs (forward-direction request routing). Public surface is the same\n * across single-MCP and config-file modes; the `namespaced` flag toggles tool-naming\n * behavior internally.\n */\nexport class Orchestrator {\n private readonly config: OrchestratorConfig;\n private readonly registry: UpstreamRegistry = new UpstreamRegistry();\n private readonly lazyRegistry: LazyRegistry = new LazyRegistry();\n private readonly toolsByMcp: Map<string, UpstreamTool[]> = new Map();\n /**\n * In-flight loads, keyed by mcpName. Used by {@link loadMcp} to coalesce concurrent\n * calls for the same name onto a single underlying connection attempt — per SPEC.md\n * § \"Dynamic Discovery > Concurrency\".\n */\n private readonly inFlightLoads: Map<string, Promise<LoadMcpResult>> = new Map();\n private resourceRouter: ResourceRouter | null = null;\n private promptRouter: PromptRouter | null = null;\n private toolCatalog: ToolCatalog | null = null;\n private aggregatedCapabilities: ServerCapabilities | null = null;\n private serverRequestForwarders: OrchestratorServerRequestForwarders = {};\n private readonly forwarder: NotificationForwarder;\n\n constructor(config: OrchestratorConfig) {\n if (!config.namespaced && config.eagerMcps.size !== 1) {\n throw new Error(\n `Single-MCP (non-namespaced) mode requires exactly one upstream; got ${config.eagerMcps.size}.`,\n );\n }\n if (!config.namespaced && config.lazyMcps !== undefined && config.lazyMcps.size > 0) {\n throw new Error(\n \"Single-MCP (non-namespaced) mode does not support lazy upstreams (descriptions).\",\n );\n }\n this.config = config;\n this.forwarder = new NotificationForwarder(\n this.registry,\n () => this.resourceRouter,\n () => this.promptRouter,\n this.toolsByMcp,\n () => this.rebuildToolCatalog(),\n this.config.namespaced,\n );\n }\n\n setNotificationHandlers(handlers: OrchestratorNotificationHandlers): void {\n this.forwarder.setHostHandlers(handlers);\n }\n\n setServerRequestForwarders(forwarders: OrchestratorServerRequestForwarders): void {\n this.serverRequestForwarders = forwarders;\n }\n\n /**\n * True when the orchestrator was configured with at least one lazy upstream MCP.\n * The `index.ts` wiring uses this to decide whether to register the `load_mcp`\n * meta-tool with the host-facing {@link ProxyServer}.\n */\n get hasDynamicDiscovery(): boolean {\n return this.config.lazyMcps !== undefined && this.config.lazyMcps.size > 0;\n }\n\n async connect(): Promise<void> {\n // Router priority order includes lazy names too — eager entries populate now, lazy\n // entries populate as `loadMcp` calls land. This way first-wins collision rules\n // are defined entirely by config-file order and don't shift around when a lazy MCP\n // joins later.\n const allNames = [...this.config.eagerMcps.keys(), ...(this.config.lazyMcps?.keys() ?? [])];\n const resourceRouter = new ResourceRouter(allNames);\n const promptRouter = new PromptRouter(allNames);\n\n if (this.config.lazyMcps !== undefined) {\n for (const [name, { transport, description }] of this.config.lazyMcps) {\n this.lazyRegistry.register(name, { transport, description });\n }\n }\n\n const upstreamEntries: ReadonlyArray<readonly [string, UpstreamConfig]> = [\n ...this.config.eagerMcps,\n ].map(([mcpName, { transport }]) => [mcpName, this.buildUpstreamConfig(mcpName, transport)]);\n\n await this.registry.connectAll(upstreamEntries);\n\n const capabilityList: (ServerCapabilities | undefined)[] = [];\n this.toolsByMcp.clear();\n\n for (const [mcpName, client] of this.registry.entries()) {\n const caps = client.getCapabilities();\n capabilityList.push(caps);\n\n const tools = await client.listTools();\n this.toolsByMcp.set(mcpName, tools);\n\n if (caps?.resources !== undefined) {\n const [resources, templates] = await Promise.all([\n client.listResources().catch(() => [] as Resource[]),\n client.listResourceTemplates().catch(() => [] as ResourceTemplate[]),\n ]);\n resourceRouter.setResources(mcpName, resources);\n resourceRouter.setTemplates(mcpName, templates);\n }\n if (caps?.prompts !== undefined) {\n const prompts = await client.listPrompts().catch(() => [] as Prompt[]);\n promptRouter.setPrompts(mcpName, prompts);\n }\n }\n\n this.resourceRouter = resourceRouter;\n this.promptRouter = promptRouter;\n this.aggregatedCapabilities = aggregateCapabilities(capabilityList);\n this.rebuildToolCatalog();\n\n logCollisions(resourceRouter, promptRouter);\n }\n\n async disconnectAll(): Promise<void> {\n await this.registry.disconnectAll();\n this.toolsByMcp.clear();\n this.toolCatalog = null;\n this.aggregatedCapabilities = null;\n this.resourceRouter = null;\n this.promptRouter = null;\n this.inFlightLoads.clear();\n }\n\n // === Dynamic discovery ===\n\n /**\n * Loads a lazy upstream MCP on demand. Implements the semantics of SPEC.md §\n * \"Tools > load_mcp\" and § \"Dynamic Discovery > Lifecycle of a Lazy MCP\":\n *\n * - Already-loaded (eager or previously-loaded lazy) names succeed as a no-op\n * returning the current listing; no notifications fire.\n * - Unknown names throw an error that hints at the still-lazy alternatives.\n * - Concurrent calls for the same name coalesce onto the same in-flight load.\n * - A failure during connect/initialize/catalog-query rolls back atomically:\n * the upstream is disconnected, the lazy entry stays registered, no host\n * notifications fire.\n * - On success the loaded MCP is promoted into the connected registry, its\n * tools/resources/prompts populate the routers, the discover_tool catalog\n * is regenerated, and the host receives `tools/list_changed` plus\n * `resources/list_changed` and/or `prompts/list_changed` for any non-empty\n * surface the MCP contributed.\n */\n async loadMcp(mcpName: string): Promise<LoadMcpResult> {\n if (this.registry.get(mcpName) !== undefined) {\n // Already connected — either eager at startup or previously loaded. Idempotent\n // no-op: return current listing without firing notifications.\n return this.getListing(mcpName);\n }\n\n const inFlight = this.inFlightLoads.get(mcpName);\n if (inFlight !== undefined) {\n return inFlight;\n }\n\n if (!this.lazyRegistry.has(mcpName)) {\n const lazyNames = this.lazyRegistry.names().join(\", \");\n const hint = lazyNames.length > 0 ? lazyNames : \"(none)\";\n throw new Error(`Unknown MCP server: \"${mcpName}\". Available servers to load: ${hint}`);\n }\n\n const loadPromise = this.runLoadPipeline(mcpName).finally(() => {\n this.inFlightLoads.delete(mcpName);\n });\n this.inFlightLoads.set(mcpName, loadPromise);\n return loadPromise;\n }\n\n private async runLoadPipeline(mcpName: string): Promise<LoadMcpResult> {\n const entry = this.lazyRegistry.get(mcpName);\n if (entry === undefined) {\n throw new Error(`Internal error: lazy entry \"${mcpName}\" vanished mid-load.`);\n }\n\n const client = await this.registry.connectOne(\n mcpName,\n this.buildUpstreamConfig(mcpName, entry.transport),\n );\n\n let tools: UpstreamTool[];\n let resources: Resource[] = [];\n let templates: ResourceTemplate[] = [];\n let prompts: Prompt[] = [];\n let caps: ServerCapabilities | undefined;\n try {\n caps = client.getCapabilities();\n tools = await client.listTools();\n\n if (caps?.resources !== undefined) {\n [resources, templates] = await Promise.all([\n client.listResources(),\n client.listResourceTemplates(),\n ]);\n }\n if (caps?.prompts !== undefined) {\n prompts = await client.listPrompts();\n }\n } catch (error) {\n // Roll back atomically: drop the half-loaded upstream. Track the failure\n // against the retry budget — once exhausted, evict the lazy entry entirely\n // and emit `tools/list_changed` so the host sees `<mcp_servers>` update.\n await this.registry.deleteOne(mcpName);\n const failures = this.lazyRegistry.recordFailure(mcpName);\n if (failures >= MAX_LOAD_ATTEMPTS) {\n this.lazyRegistry.take(mcpName);\n this.rebuildToolCatalog();\n await this.forwarder.notifyToolsListChanged();\n const base = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Failed to load \"${mcpName}\" after ${failures} attempts; the server will no longer be offered for discovery. Underlying error: ${base}`,\n );\n }\n throw error;\n }\n\n // Commit phase: from here on every step is purely local mutation, so the load is\n // atomic in practice — we've succeeded in talking to the upstream, and updating\n // local state cannot fail in a way that leaves us with a phantom load.\n this.lazyRegistry.take(mcpName);\n this.toolsByMcp.set(mcpName, tools);\n const resourceRouter = this.requireResourceRouter();\n const promptRouter = this.requirePromptRouter();\n if (caps?.resources !== undefined) {\n resourceRouter.setResources(mcpName, resources);\n resourceRouter.setTemplates(mcpName, templates);\n }\n if (caps?.prompts !== undefined) {\n promptRouter.setPrompts(mcpName, prompts);\n }\n this.rebuildToolCatalog();\n\n // Emit notifications. `tools/list_changed` always — the catalog and the\n // `<mcp_servers>` block both changed. Resource/prompt notifications are emitted\n // only when the MCP contributed entries (per SPEC.md § \"load_mcp\").\n await this.forwarder.notifyToolsListChanged();\n if (caps?.resources !== undefined && (resources.length > 0 || templates.length > 0)) {\n await this.forwarder.notifyResourcesListChanged();\n }\n if (caps?.prompts !== undefined && prompts.length > 0) {\n await this.forwarder.notifyPromptsListChanged();\n }\n\n return this.getListing(mcpName);\n }\n\n /**\n * Builds the structured response shape documented for `load_mcp` from existing\n * per-MCP state. Pulled out into a helper so the no-op path (already-loaded)\n * and the success path share one source of truth.\n */\n private getListing(mcpName: string): LoadMcpResult {\n const tools = this.toolsByMcp.get(mcpName) ?? [];\n const namespacedToolName = (name: string): string =>\n this.config.namespaced ? `${mcpName}/${name}` : name;\n\n const resources = this.resourceRouter?.resourcesFor(mcpName) ?? [];\n const templates = this.resourceRouter?.templatesFor(mcpName) ?? [];\n const prompts = this.promptRouter?.promptsFor(mcpName) ?? [];\n\n return {\n mcp_name: mcpName,\n tools: tools.map(tool => ({\n name: namespacedToolName(tool.name),\n description: tool.description,\n })),\n resources: resources.map(resource => ({\n uri: resource.uri,\n name: resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n })),\n resource_templates: templates.map(template => ({\n uriTemplate: template.uriTemplate,\n name: template.name,\n description: template.description,\n mimeType: template.mimeType,\n })),\n prompts: prompts.map(prompt => ({\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n })),\n };\n }\n\n // === Internal helpers used by connect() and loadMcp() ===\n\n private buildUpstreamConfig(mcpName: string, transport: Transport): UpstreamConfig {\n return {\n transport,\n onTransportError: (error: Error) => {\n this.config.onTransportError?.(mcpName, error);\n },\n notifications: {\n onToolsListChanged: () => this.forwarder.handleToolsListChanged(mcpName),\n onResourcesListChanged: () => this.forwarder.handleResourcesListChanged(mcpName),\n onResourceUpdated: params => this.forwarder.handleResourceUpdated(params),\n onPromptsListChanged: () => this.forwarder.handlePromptsListChanged(mcpName),\n onLogMessage: params => this.forwarder.handleLogMessage(mcpName, params),\n },\n serverRequests: {\n onCreateMessage: (params, opts) => this.forwardCreateMessage(params, opts),\n onElicitInput: (params, opts) => this.forwardElicitInput(params, opts),\n onListRoots: (params, opts) => this.forwardListRoots(params, opts),\n },\n };\n }\n\n /**\n * Rebuilds the `ToolCatalog` from current state. Called whenever `toolsByMcp` or the\n * lazy-registry membership changes — including initial connect, upstream-emitted\n * `tools/list_changed`, and successful `loadMcp`.\n */\n private rebuildToolCatalog(): void {\n if (this.config.namespaced) {\n this.toolCatalog = ToolCatalog.fromGroupedWithLazy(\n this.toolsByMcp,\n this.lazyRegistry.descriptions(),\n );\n } else {\n this.toolCatalog = ToolCatalog.fromFlat([...this.toolsByMcp.values()][0] ?? []);\n }\n }\n\n get catalog(): ToolCatalog {\n if (this.toolCatalog === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.toolCatalog;\n }\n\n get capabilities(): ServerCapabilities {\n if (this.aggregatedCapabilities === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.aggregatedCapabilities;\n }\n\n // === Forward-direction request routing ===\n\n async callTool(\n displayName: string,\n input: Record<string, unknown>,\n options?: CallOptions,\n ): Promise<CallToolResult> {\n if (this.config.namespaced) {\n const { mcpName, toolName } = splitNamespacedName(displayName, this.registry.names());\n return this.requireClient(mcpName, \"tool\").callTool(toolName, input, options);\n }\n\n const sole = this.registry.sole();\n if (sole === undefined) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return sole.callTool(displayName, input, options);\n }\n\n listResources(): Resource[] {\n return this.requireResourceRouter().aggregatedResources();\n }\n\n listResourceTemplates(): ResourceTemplate[] {\n return this.requireResourceRouter().aggregatedTemplates();\n }\n\n async readResource(uri: string, options?: CallOptions): Promise<ReadResourceResult> {\n return this.resolveResourceOwner(uri).readResource(uri, options);\n }\n\n async subscribeResource(uri: string, options?: CallOptions): Promise<void> {\n await this.resolveResourceOwner(uri).subscribeResource(uri, options);\n }\n\n async unsubscribeResource(uri: string, options?: CallOptions): Promise<void> {\n await this.resolveResourceOwner(uri).unsubscribeResource(uri, options);\n }\n\n listPrompts(): Prompt[] {\n return this.requirePromptRouter().aggregatedPrompts();\n }\n\n async getPrompt(\n name: string,\n args?: Record<string, string>,\n options?: CallOptions,\n ): Promise<GetPromptResult> {\n return this.resolvePromptOwner(name).getPrompt(name, args, options);\n }\n\n async complete(\n params: CompleteRequest[\"params\"],\n options?: CallOptions,\n ): Promise<CompleteResult> {\n const client = this.resolveCompletionTarget(params.ref);\n return client.complete(params, options);\n }\n\n // === Broadcasts ===\n\n /**\n * Broadcasts a `logging/setLevel` request to every upstream advertising the logging\n * capability. Errors from individual upstreams are swallowed so a single misbehaving\n * upstream cannot break the broadcast for others; failures are written to stderr.\n */\n async setLoggingLevel(level: LoggingLevel, options?: CallOptions): Promise<void> {\n await this.broadcastAsync(\n client =>\n client.getCapabilities()?.logging !== undefined\n ? client.setLoggingLevel(level, options)\n : Promise.resolve(),\n \"setLoggingLevel\",\n );\n }\n\n /**\n * Broadcasts `notifications/roots/list_changed` to every connected upstream — the\n * proxy declares roots capability uniformly to all upstreams so every one of them\n * may have requested roots and needs to know the list changed.\n */\n async broadcastRootsListChanged(): Promise<void> {\n await this.broadcastAsync(client => client.sendRootsListChanged(), \"sendRootsListChanged\");\n }\n\n // === Server-initiated request forwarders (upstream → host) ===\n\n private async forwardCreateMessage(\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<CreateMessageResult> {\n const handler = this.serverRequestForwarders.onCreateMessage;\n if (handler === undefined) {\n throw new Error(\"Proxy does not support sampling: host has not registered a handler.\");\n }\n return handler(params, options);\n }\n\n private async forwardElicitInput(\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ElicitResult> {\n const handler = this.serverRequestForwarders.onElicitInput;\n if (handler === undefined) {\n throw new Error(\"Proxy does not support elicitation: host has not registered a handler.\");\n }\n return handler(params, options);\n }\n\n private async forwardListRoots(\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ListRootsResult> {\n const handler = this.serverRequestForwarders.onListRoots;\n if (handler === undefined) {\n throw new Error(\"Proxy does not support roots: host has not registered a handler.\");\n }\n return handler(params, options);\n }\n\n // === Internal helpers ===\n\n private requireResourceRouter(): ResourceRouter {\n if (this.resourceRouter === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.resourceRouter;\n }\n\n private requirePromptRouter(): PromptRouter {\n if (this.promptRouter === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.promptRouter;\n }\n\n private resolveResourceOwner(uri: string): UpstreamClient {\n const owner = this.requireResourceRouter().ownerOf(uri);\n if (owner === undefined) {\n throw new Error(`Unknown resource URI: \"${uri}\". No upstream MCP advertises it.`);\n }\n return this.requireClient(owner, \"resource\");\n }\n\n private resolvePromptOwner(name: string): UpstreamClient {\n const owner = this.requirePromptRouter().ownerOf(name);\n if (owner === undefined) {\n throw new Error(`Unknown prompt: \"${name}\". No upstream MCP advertises it.`);\n }\n return this.requireClient(owner, \"prompt\");\n }\n\n private resolveCompletionTarget(ref: CompleteRequest[\"params\"][\"ref\"]): UpstreamClient {\n if (ref.type === \"ref/prompt\") {\n return this.resolvePromptOwner(ref.name);\n }\n if (ref.type === \"ref/resource\") {\n return this.resolveResourceOwner(ref.uri);\n }\n const unknownRef: { type: string } = ref;\n throw new Error(`Unsupported completion ref type: \"${unknownRef.type}\"`);\n }\n\n private requireClient(mcpName: string, role: string): UpstreamClient {\n const client = this.registry.get(mcpName);\n if (client === undefined) {\n throw new Error(`Internal error: ${role} owner \"${mcpName}\" has no connected client.`);\n }\n return client;\n }\n\n private async broadcastAsync(\n action: (client: UpstreamClient) => Promise<void>,\n label: string,\n ): Promise<void> {\n const targets: Promise<void>[] = [];\n for (const [mcpName, client] of this.registry.entries()) {\n targets.push(\n action(client).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`dynmcp: ${label} failed for \"${mcpName}\": ${message}\\n`);\n }),\n );\n }\n await Promise.all(targets);\n }\n}\n\nfunction splitNamespacedName(\n namespacedName: string,\n knownMcpNames: readonly string[],\n): { mcpName: string; toolName: string } {\n const separatorIndex = namespacedName.indexOf(\"/\");\n if (separatorIndex === -1) {\n throw new Error(\n `Invalid namespaced tool name: \"${namespacedName}\". Expected format: \"mcpName/toolName\".`,\n );\n }\n\n const mcpName = namespacedName.slice(0, separatorIndex);\n const toolName = namespacedName.slice(separatorIndex + 1);\n\n if (!knownMcpNames.includes(mcpName)) {\n const available = [...knownMcpNames].sort().join(\", \");\n throw new Error(`Unknown MCP: \"${mcpName}\". Available MCPs: ${available}`);\n }\n\n return { mcpName, toolName };\n}\n\nfunction logCollisions(resourceRouter: ResourceRouter, promptRouter: PromptRouter): void {\n for (const collision of resourceRouter.collisions()) {\n process.stderr.write(\n `dynmcp: resource URI collision: \"${collision.uri}\" is provided by ` +\n `\"${collision.chosen}\" and \"${collision.shadowed}\"; routing to \"${collision.chosen}\".\\n`,\n );\n }\n for (const collision of promptRouter.collisions()) {\n process.stderr.write(\n `dynmcp: prompt name collision: \"${collision.name}\" is provided by ` +\n `\"${collision.chosen}\" and \"${collision.shadowed}\"; routing to \"${collision.chosen}\".\\n`,\n );\n }\n}\n","import type { ServerCapabilities } from \"@modelcontextprotocol/sdk/types.js\";\n\n/**\n * Aggregates the capabilities advertised by every upstream MCP into the single\n * capability set that the proxy will advertise to the host during `initialize`.\n *\n * Rules (per SPEC.md \"Capability Aggregation\"):\n *\n * - `tools` is always advertised — the proxy itself exposes `discover_tool` and `use_tool`\n * regardless of upstream support.\n * - `tools.listChanged` is always advertised — the proxy emits it when any upstream's tool\n * list changes, even when no individual upstream supports the notification.\n * - All other capabilities (`resources`, `prompts`, `logging`, `completions`) are advertised\n * iff at least one upstream advertises them. Nested booleans (`subscribe`, `listChanged`)\n * are advertised iff at least one supporting upstream advertises them.\n */\nexport function aggregateCapabilities(\n upstreams: ReadonlyArray<ServerCapabilities | undefined>,\n): ServerCapabilities {\n const aggregated: ServerCapabilities = {\n tools: { listChanged: true },\n };\n\n for (const caps of upstreams) {\n if (caps === undefined) continue;\n\n if (caps.resources !== undefined) {\n aggregated.resources ??= {};\n if (caps.resources.subscribe === true) {\n aggregated.resources.subscribe = true;\n }\n if (caps.resources.listChanged === true) {\n aggregated.resources.listChanged = true;\n }\n }\n\n if (caps.prompts !== undefined) {\n aggregated.prompts ??= {};\n if (caps.prompts.listChanged === true) {\n aggregated.prompts.listChanged = true;\n }\n }\n\n if (caps.logging !== undefined) {\n aggregated.logging ??= {};\n }\n\n if (caps.completions !== undefined) {\n aggregated.completions ??= {};\n }\n }\n\n return aggregated;\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\n\n/**\n * One unconnected lazy upstream MCP. Held by {@link LazyRegistry} until a `load_mcp`\n * call promotes it to a connected upstream in the {@link UpstreamRegistry}.\n *\n * The transport is constructed at startup (so a misconfigured transport surfaces\n * before any host traffic arrives) but is not actually opened until load time —\n * {@link UpstreamClient.connect} is what opens the underlying connection.\n */\nexport type LazyEntry = {\n readonly description: string;\n readonly transport: Transport;\n};\n\n/**\n * Stores the lazy-loading-eligible upstream MCPs declared in the config file —\n * those entries that carry a `description` field. The registry preserves the\n * config-file insertion order so the `<mcp_servers>` block in `discover_tool`'s\n * description renders in a stable order matching the user's config.\n *\n * Once a lazy MCP transitions to `loaded` (via the orchestrator's `loadMcp`\n * pipeline), {@link take} is called to remove it from this registry. There is\n * no \"unloaded\" state by design — see SPEC.md § \"Dynamic Discovery > Lifecycle\".\n *\n * Failed loads are tracked per-entry via {@link recordFailure}. After enough\n * consecutive failures the orchestrator will evict the entry — this prevents\n * an agent from burning forever on a broken upstream while still tolerating\n * transient hiccups.\n */\nexport class LazyRegistry {\n private readonly entries: Map<string, LazyEntry> = new Map();\n private readonly failureCounts: Map<string, number> = new Map();\n\n register(name: string, entry: LazyEntry): void {\n if (this.entries.has(name)) {\n throw new Error(`LazyRegistry: duplicate registration for \"${name}\"`);\n }\n this.entries.set(name, entry);\n }\n\n has(name: string): boolean {\n return this.entries.has(name);\n }\n\n get(name: string): LazyEntry | undefined {\n return this.entries.get(name);\n }\n\n /**\n * Records a failed load attempt and returns the new total. The orchestrator's\n * retry-budget logic uses this to decide whether to evict the entry. A\n * subsequent successful load (or {@link take}) clears the count.\n */\n recordFailure(name: string): number {\n const next = (this.failureCounts.get(name) ?? 0) + 1;\n this.failureCounts.set(name, next);\n return next;\n }\n\n failureCount(name: string): number {\n return this.failureCounts.get(name) ?? 0;\n }\n\n /**\n * Returns the descriptions of every still-lazy MCP in insertion order. Consumed\n * by {@link ToolCatalog.fromGroupedWithLazy} to render the `<mcp_servers>` block.\n */\n descriptions(): ReadonlyMap<string, string> {\n const result = new Map<string, string>();\n for (const [name, entry] of this.entries) {\n result.set(name, entry.description);\n }\n return result;\n }\n\n /**\n * Returns the names of every still-lazy MCP in insertion order. Used by error\n * messages that need to hint the agent at what is loadable.\n */\n names(): readonly string[] {\n return [...this.entries.keys()];\n }\n\n size(): number {\n return this.entries.size;\n }\n\n /**\n * Removes and returns the entry, signalling that the upstream has been (or is\n * about to be) promoted to a connected client (or evicted after exhausting\n * its retry budget). The caller is responsible for ensuring the promotion\n * actually succeeds — failed loads should re-register via {@link register} to\n * roll back the state. Clears the failure count along with the entry.\n */\n take(name: string): LazyEntry | undefined {\n const entry = this.entries.get(name);\n if (entry === undefined) return undefined;\n this.entries.delete(name);\n this.failureCounts.delete(name);\n return entry;\n }\n}\n","import type { Prompt, Resource, ResourceTemplate } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { PromptRouter } from \"./prompt-router.js\";\nimport type { ResourceRouter } from \"./resource-router.js\";\nimport type { LogMessageParams, UpstreamTool } from \"./upstream-client.js\";\nimport type { UpstreamRegistry } from \"./upstream-registry.js\";\n\n/**\n * Callbacks the proxy uses to push notifications out to the host once an upstream\n * has emitted the equivalent inbound notification. The {@link NotificationForwarder}\n * is the seam between the upstream-side notification handlers (which it owns) and\n * the host-side outbound calls (which the caller provides).\n */\nexport type HostNotificationHandlers = {\n onToolsListChanged?: () => void | Promise<void>;\n onResourcesListChanged?: () => void | Promise<void>;\n onResourceUpdated?: (params: { uri: string }) => void | Promise<void>;\n onPromptsListChanged?: () => void | Promise<void>;\n onLogMessage?: (params: LogMessageParams) => void | Promise<void>;\n};\n\n/**\n * Translates upstream-emitted notifications into proxy-emitted notifications sent\n * to the host. For list-change notifications this includes re-fetching the affected\n * data from the originating upstream and updating the shared catalogs/routers before\n * propagating the change. For log messages it rewrites the `logger` field with the\n * `<mcp-name>/` prefix in config-file mode.\n *\n * The forwarder holds references to mutable state (the tool catalog, the routers)\n * and is expected to be co-owned with whatever assembles that state — typically the\n * Orchestrator. Catalog rebuilds are performed via the {@link buildToolCatalog}\n * callback so the Orchestrator stays the single owner of the catalog reference.\n */\nexport class NotificationForwarder {\n private hostHandlers: HostNotificationHandlers = {};\n\n constructor(\n private readonly registry: UpstreamRegistry,\n private readonly resourceRouter: () => ResourceRouter | null,\n private readonly promptRouter: () => PromptRouter | null,\n private readonly toolsByMcp: Map<string, UpstreamTool[]>,\n /**\n * Asks the orchestrator to rebuild the tool catalog from current state\n * (`toolsByMcp` plus, when dynamic discovery is enabled, the lazy registry's\n * descriptions). The forwarder doesn't own that composition itself so this stays\n * a single seam.\n */\n private readonly rebuildToolCatalog: () => void,\n private readonly namespaced: boolean,\n ) {}\n\n setHostHandlers(handlers: HostNotificationHandlers): void {\n this.hostHandlers = handlers;\n }\n\n async handleToolsListChanged(mcpName: string): Promise<void> {\n const client = this.registry.get(mcpName);\n if (client === undefined) return;\n\n const tools = await client.listTools().catch(() => [] as UpstreamTool[]);\n this.toolsByMcp.set(mcpName, tools);\n this.rebuildToolCatalog();\n\n await this.hostHandlers.onToolsListChanged?.();\n }\n\n async handleResourcesListChanged(mcpName: string): Promise<void> {\n const router = this.resourceRouter();\n const client = this.registry.get(mcpName);\n if (router === null || client === undefined) return;\n\n const [resources, templates] = await Promise.all([\n client.listResources().catch(() => [] as Resource[]),\n client.listResourceTemplates().catch(() => [] as ResourceTemplate[]),\n ]);\n router.setResources(mcpName, resources);\n router.setTemplates(mcpName, templates);\n\n await this.hostHandlers.onResourcesListChanged?.();\n }\n\n async handleResourceUpdated(params: { uri: string }): Promise<void> {\n await this.hostHandlers.onResourceUpdated?.(params);\n }\n\n /**\n * Fire-only emitters. Unlike `handleXListChanged`, these do not re-fetch the\n * affected data from any upstream — the caller has already populated the relevant\n * state directly. Used by the orchestrator's load_mcp pipeline, which already has\n * the freshly-queried tools/resources/prompts in hand and just needs to nudge the\n * host to refetch.\n */\n async notifyToolsListChanged(): Promise<void> {\n await this.hostHandlers.onToolsListChanged?.();\n }\n\n async notifyResourcesListChanged(): Promise<void> {\n await this.hostHandlers.onResourcesListChanged?.();\n }\n\n async notifyPromptsListChanged(): Promise<void> {\n await this.hostHandlers.onPromptsListChanged?.();\n }\n\n async handlePromptsListChanged(mcpName: string): Promise<void> {\n const router = this.promptRouter();\n const client = this.registry.get(mcpName);\n if (router === null || client === undefined) return;\n\n const prompts = await client.listPrompts().catch(() => [] as Prompt[]);\n router.setPrompts(mcpName, prompts);\n\n await this.hostHandlers.onPromptsListChanged?.();\n }\n\n /**\n * Rewrites the upstream's `logger` field with the originating MCP's name as a\n * prefix so the host can attribute log lines, then forwards the message to the\n * host's log message handler.\n */\n async handleLogMessage(mcpName: string, params: LogMessageParams): Promise<void> {\n const handler = this.hostHandlers.onLogMessage;\n if (handler === undefined) return;\n\n if (!this.namespaced) {\n await handler(params);\n return;\n }\n\n const prefixed: LogMessageParams = {\n ...params,\n logger: params.logger === undefined ? mcpName : `${mcpName}/${params.logger}`,\n };\n await handler(prefixed);\n }\n}\n","import type { Prompt } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type PromptCollision = {\n name: string;\n chosen: string;\n shadowed: string;\n};\n\n/**\n * Tracks which upstream MCP owns each prompt name exposed through the proxy and\n * resolves the owner for any `prompts/get` or `completion/complete` request that\n * references a prompt by name.\n *\n * Collision rule: when two upstreams advertise the same prompt name, the upstream\n * appearing first in config-file order wins; the shadowed upstream's prompt is\n * unreachable through the proxy until the conflict is resolved upstream.\n */\nexport class PromptRouter {\n private readonly mcpOrder: string[];\n private readonly perMcp: Map<string, Prompt[]>;\n\n private nameOwners: Map<string, string> = new Map();\n private detectedCollisions: PromptCollision[] = [];\n\n constructor(mcpOrder: readonly string[]) {\n this.mcpOrder = [...mcpOrder];\n this.perMcp = new Map(this.mcpOrder.map(name => [name, [] as Prompt[]]));\n }\n\n setPrompts(mcpName: string, prompts: Prompt[]): void {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) {\n throw new Error(`PromptRouter: unknown mcp \"${mcpName}\"`);\n }\n this.perMcp.set(mcpName, [...prompts]);\n this.rebuild();\n }\n\n aggregatedPrompts(): Prompt[] {\n const result: Prompt[] = [];\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry !== undefined) {\n result.push(...entry);\n }\n }\n return result;\n }\n\n ownerOf(promptName: string): string | undefined {\n return this.nameOwners.get(promptName);\n }\n\n collisions(): readonly PromptCollision[] {\n return this.detectedCollisions;\n }\n\n /**\n * Returns the prompts contributed by a single upstream MCP. Used by the load_mcp\n * pipeline to construct its structured response. Returns an empty array if the MCP\n * has not contributed any prompts (or if `mcpName` is unknown).\n */\n promptsFor(mcpName: string): readonly Prompt[] {\n return this.perMcp.get(mcpName) ?? [];\n }\n\n private rebuild(): void {\n this.nameOwners = new Map();\n const collisions: PromptCollision[] = [];\n\n for (const mcpName of this.mcpOrder) {\n const prompts = this.perMcp.get(mcpName);\n if (prompts === undefined) continue;\n\n for (const prompt of prompts) {\n const existing = this.nameOwners.get(prompt.name);\n if (existing === undefined) {\n this.nameOwners.set(prompt.name, mcpName);\n } else {\n collisions.push({ name: prompt.name, chosen: existing, shadowed: mcpName });\n }\n }\n }\n\n this.detectedCollisions = collisions;\n }\n}\n","import type { Resource, ResourceTemplate } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type ResourceCollision = {\n uri: string;\n chosen: string;\n shadowed: string;\n};\n\n/**\n * Tracks which upstream MCP owns each resource URI exposed through the proxy and\n * resolves the owner for any `resources/read`, `resources/subscribe`, or\n * `resources/unsubscribe` request.\n *\n * Collision rule: when two upstreams advertise the same concrete URI, the upstream\n * appearing first in config-file order wins; the shadowed upstream's copy of that\n * resource is unreachable through the proxy until the conflict is resolved upstream.\n *\n * Template URIs (RFC 6570 forms like `file:///{path}`) are matched against incoming\n * URIs by their literal prefix (everything before the first `{`). When more than one\n * upstream advertises an overlapping template, the first-wins rule applies on a\n * prefix-equality basis.\n *\n * Concrete URI matches always take precedence over template matches, regardless of\n * config order.\n */\nexport class ResourceRouter {\n private readonly mcpOrder: string[];\n private readonly perMcp: Map<string, { resources: Resource[]; templates: ResourceTemplate[] }>;\n\n private uriOwners: Map<string, string> = new Map();\n private templateOwners: Array<{ prefix: string; template: ResourceTemplate; mcpName: string }> =\n [];\n private detectedCollisions: ResourceCollision[] = [];\n\n constructor(mcpOrder: readonly string[]) {\n this.mcpOrder = [...mcpOrder];\n this.perMcp = new Map(\n this.mcpOrder.map(name => [name, { resources: [], templates: [] }] as const),\n );\n }\n\n setResources(mcpName: string, resources: Resource[]): void {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) {\n throw new Error(`ResourceRouter: unknown mcp \"${mcpName}\"`);\n }\n entry.resources = [...resources];\n this.rebuild();\n }\n\n setTemplates(mcpName: string, templates: ResourceTemplate[]): void {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) {\n throw new Error(`ResourceRouter: unknown mcp \"${mcpName}\"`);\n }\n entry.templates = [...templates];\n this.rebuild();\n }\n\n aggregatedResources(): Resource[] {\n const result: Resource[] = [];\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry !== undefined) {\n result.push(...entry.resources);\n }\n }\n return result;\n }\n\n aggregatedTemplates(): ResourceTemplate[] {\n const result: ResourceTemplate[] = [];\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry !== undefined) {\n result.push(...entry.templates);\n }\n }\n return result;\n }\n\n /**\n * Returns the mcpName that owns the given URI, or undefined if no upstream advertises it.\n * Concrete URI matches take precedence over template prefix matches; templates are tried\n * in config-file order (first-wins).\n */\n ownerOf(uri: string): string | undefined {\n const concrete = this.uriOwners.get(uri);\n if (concrete !== undefined) {\n return concrete;\n }\n\n for (const { prefix, mcpName } of this.templateOwners) {\n if (prefix.length > 0 && uri.startsWith(prefix)) {\n return mcpName;\n }\n }\n\n return undefined;\n }\n\n collisions(): readonly ResourceCollision[] {\n return this.detectedCollisions;\n }\n\n /**\n * Returns the resources contributed by a single upstream MCP. Used by the load_mcp\n * pipeline to construct its structured response, which lists what a just-loaded MCP\n * (or an already-loaded MCP, in the idempotent no-op path) brought to the proxy.\n * Returns an empty array if the MCP has not contributed any resources (or if\n * `mcpName` is unknown).\n */\n resourcesFor(mcpName: string): readonly Resource[] {\n return this.perMcp.get(mcpName)?.resources ?? [];\n }\n\n templatesFor(mcpName: string): readonly ResourceTemplate[] {\n return this.perMcp.get(mcpName)?.templates ?? [];\n }\n\n private rebuild(): void {\n this.uriOwners = new Map();\n this.templateOwners = [];\n const collisions: ResourceCollision[] = [];\n\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) continue;\n\n for (const resource of entry.resources) {\n const existing = this.uriOwners.get(resource.uri);\n if (existing === undefined) {\n this.uriOwners.set(resource.uri, mcpName);\n } else {\n collisions.push({ uri: resource.uri, chosen: existing, shadowed: mcpName });\n }\n }\n\n for (const template of entry.templates) {\n this.templateOwners.push({\n prefix: literalPrefixOf(template.uriTemplate),\n template,\n mcpName,\n });\n }\n }\n\n this.detectedCollisions = collisions;\n }\n}\n\nfunction literalPrefixOf(uriTemplate: string): string {\n const idx = uriTemplate.indexOf(\"{\");\n return idx === -1 ? uriTemplate : uriTemplate.slice(0, idx);\n}\n","import type { UpstreamTool } from \"./upstream-client.js\";\n\nconst DISCOVER_TOOL_PREAMBLE = `Use this tool to look up the full schema of a tool before calling it with use_tool.\nCall discover_tool with a tool name from the list below to get its complete description,\ninput parameters, and output schema. Always discover a tool before using it.`;\n\nconst DYNAMIC_DISCOVERY_PREAMBLE = `Some MCP servers below are not loaded yet and are listed under <mcp_servers> with a\nshort description of what they do. To make a server's tools (and any resources or\nprompts it exposes) available, call load_mcp with its name. Once loaded, the server's\ntools will appear in the <tools> list and become callable via use_tool. Loading is\npermanent for the remainder of this session.`;\n\nconst NO_TOOLS_LOADED_FOOTER =\n \"No tools are currently loaded. Call load_mcp to make a server's tools available.\";\n\nexport class ToolCatalog {\n readonly tools: ReadonlyMap<string, UpstreamTool>;\n readonly discoverToolDescription: string;\n\n private constructor(tools: Map<string, UpstreamTool>, description: string) {\n this.tools = tools;\n this.discoverToolDescription = description;\n }\n\n static fromFlat(upstreamTools: UpstreamTool[]): ToolCatalog {\n const toolMap = new Map<string, UpstreamTool>();\n for (const tool of upstreamTools) {\n toolMap.set(tool.name, tool);\n }\n const description = buildFlatDescription(upstreamTools);\n return new ToolCatalog(toolMap, description);\n }\n\n static fromGrouped(groups: Map<string, UpstreamTool[]>): ToolCatalog {\n return ToolCatalog.fromGroupedWithLazy(groups, new Map());\n }\n\n /**\n * Same as {@link fromGrouped} but additionally accepts a map of lazy upstream MCPs\n * (those declared with a `description` field but not yet loaded). When the map is\n * non-empty, the rendered `discover_tool` description includes a `<mcp_servers>`\n * block listing them with their descriptions and an explanatory paragraph telling\n * the agent how to call `load_mcp`. When `groups` is empty, the `<tools>` block is\n * omitted in favor of a trailing sentence directing the agent to `load_mcp`.\n */\n static fromGroupedWithLazy(\n groups: Map<string, UpstreamTool[]>,\n lazyDescriptions: ReadonlyMap<string, string>,\n ): ToolCatalog {\n const toolMap = new Map<string, UpstreamTool>();\n for (const [mcpName, tools] of groups) {\n for (const tool of tools) {\n toolMap.set(`${mcpName}/${tool.name}`, tool);\n }\n }\n const description = buildGroupedDescription(groups, lazyDescriptions);\n return new ToolCatalog(toolMap, description);\n }\n\n getToolDetails(toolName: string): string {\n const tool = this.tools.get(toolName);\n\n if (tool === undefined) {\n const sortedNames = [...this.tools.keys()].sort().join(\", \");\n return `Unknown tool: \"${toolName}\". Available tools: ${sortedNames}`;\n }\n\n return buildToolDetailsString(toolName, tool);\n }\n}\n\nfunction buildFlatDescription(tools: UpstreamTool[]): string {\n const sortedTools = [...tools].sort((a, b) => a.name.localeCompare(b.name));\n const toolLines = sortedTools.map(tool => `- ${tool.name}: ${tool.description}`).join(\"\\n\");\n\n return `${DISCOVER_TOOL_PREAMBLE}\\n\\n<tools>\\n${toolLines}\\n</tools>`;\n}\n\nfunction buildGroupedDescription(\n groups: Map<string, UpstreamTool[]>,\n lazyDescriptions: ReadonlyMap<string, string>,\n): string {\n const parts: string[] = [DISCOVER_TOOL_PREAMBLE];\n\n if (lazyDescriptions.size > 0) {\n parts.push(DYNAMIC_DISCOVERY_PREAMBLE);\n parts.push(buildMcpServersBlock(lazyDescriptions));\n }\n\n if (groups.size > 0) {\n parts.push(buildToolsBlock(groups));\n } else if (lazyDescriptions.size > 0) {\n parts.push(NO_TOOLS_LOADED_FOOTER);\n } else {\n // No eager tools and no lazy MCPs — render an empty <tools> block to keep the\n // shape consistent with the non-dynamic case where the host expected a block.\n parts.push(\"<tools>\\n</tools>\");\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nfunction buildToolsBlock(groups: Map<string, UpstreamTool[]>): string {\n const sortedMcpNames = [...groups.keys()].sort();\n const sections = sortedMcpNames.map(mcpName => {\n const tools = groups.get(mcpName)!;\n const sortedTools = [...tools].sort((a, b) => a.name.localeCompare(b.name));\n // Bullets render bare tool names under the group header (per SPEC.md).\n // The namespaced form (`<mcp-name>/<tool-name>`) is what callers must pass\n // to discover_tool / use_tool — the group header on the prior line tells\n // the agent which prefix to combine with each bullet.\n const toolLines = sortedTools.map(tool => `- ${tool.name}: ${tool.description}`).join(\"\\n\");\n return `${mcpName}:\\n${toolLines}`;\n });\n\n return `<tools>\\n${sections.join(\"\\n\\n\")}\\n</tools>`;\n}\n\nfunction buildMcpServersBlock(lazyDescriptions: ReadonlyMap<string, string>): string {\n // Preserve insertion order (config-file order) rather than sorting alphabetically,\n // so the user's config layout is what the agent sees.\n const lines = [...lazyDescriptions].map(([name, desc]) => `- ${name}: ${desc}`).join(\"\\n\");\n return `<mcp_servers>\\n${lines}\\n</mcp_servers>`;\n}\n\nfunction buildToolDetailsString(displayName: string, tool: UpstreamTool): string {\n const lines: string[] = [\n `Tool: ${displayName}`,\n `Description: ${tool.description}`,\n \"\",\n \"Input Schema:\",\n JSON.stringify(tool.inputSchema, null, 2),\n ];\n\n if (tool.outputSchema !== undefined) {\n lines.push(\"\", \"Output Schema:\", JSON.stringify(tool.outputSchema, null, 2));\n }\n\n const annotationLines = buildAnnotationLines(tool);\n if (annotationLines.length > 0) {\n lines.push(\"\", \"Annotations:\", ...annotationLines);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction buildAnnotationLines(tool: UpstreamTool): string[] {\n if (tool.annotations === undefined) {\n return [];\n }\n\n const { annotations } = tool;\n const lines: string[] = [];\n\n if (annotations.title !== undefined) {\n lines.push(`- title: ${annotations.title}`);\n }\n if (annotations.readOnlyHint !== undefined) {\n lines.push(`- readOnlyHint: ${annotations.readOnlyHint}`);\n }\n if (annotations.destructiveHint !== undefined) {\n lines.push(`- destructiveHint: ${annotations.destructiveHint}`);\n }\n if (annotations.idempotentHint !== undefined) {\n lines.push(`- idempotentHint: ${annotations.idempotentHint}`);\n }\n if (annotations.openWorldHint !== undefined) {\n lines.push(`- openWorldHint: ${annotations.openWorldHint}`);\n }\n\n return lines;\n}\n","import process from \"node:process\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n type CallToolResult,\n type CompleteRequest,\n type CompleteResult,\n type CreateMessageRequest,\n type CreateMessageResult,\n CreateMessageRequestSchema,\n type ElicitRequest,\n type ElicitResult,\n ElicitRequestSchema,\n type GetPromptResult,\n type ListRootsRequest,\n type ListRootsResult,\n ListRootsRequestSchema,\n type LoggingLevel,\n type LoggingMessageNotification,\n LoggingMessageNotificationSchema,\n type Prompt,\n PromptListChangedNotificationSchema,\n type ReadResourceResult,\n type Resource,\n ResourceListChangedNotificationSchema,\n type ResourceTemplate,\n ResourceUpdatedNotificationSchema,\n type ServerCapabilities,\n ToolListChangedNotificationSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type LogMessageParams = LoggingMessageNotification[\"params\"];\n\nexport type ToolAnnotations = {\n title?: string;\n readOnlyHint?: boolean;\n destructiveHint?: boolean;\n idempotentHint?: boolean;\n openWorldHint?: boolean;\n};\n\nexport type UpstreamTool = {\n name: string;\n description: string;\n inputSchema: unknown;\n outputSchema?: unknown;\n annotations?: ToolAnnotations;\n};\n\nexport type UpstreamNotificationHandlers = {\n onToolsListChanged?: () => void | Promise<void>;\n onResourcesListChanged?: () => void | Promise<void>;\n onResourceUpdated?: (params: { uri: string }) => void | Promise<void>;\n onPromptsListChanged?: () => void | Promise<void>;\n onLogMessage?: (params: LogMessageParams) => void | Promise<void>;\n};\n\n/**\n * Progress event payload as observed on a forward-direction call. The SDK Client\n * auto-assigns a progress token for our outbound request, so the upstream's\n * `notifications/progress` for that request are routed here. The proxy translates\n * these into a fresh `notifications/progress` to the host under the host's original\n * progress token.\n */\nexport type ProgressEvent = {\n progress: number;\n total?: number;\n message?: string;\n};\n\n/**\n * Per-call options forwarded to the SDK so cancellation and progress can propagate\n * from the host down to the upstream MCP and back.\n *\n * - `signal`: aborting the host's incoming request aborts this signal, which causes\n * the SDK client to emit `notifications/cancelled` to the upstream.\n * - `onprogress`: invoked whenever the upstream emits a progress notification for\n * the in-flight request. The proxy translates these into host-facing progress\n * notifications under the host's original progress token.\n */\nexport type UpstreamCallOptions = {\n signal?: AbortSignal;\n onprogress?: (progress: ProgressEvent) => void;\n};\n\n/**\n * Reverse-direction handlers invoked when an upstream MCP sends a server-initiated\n * request to the proxy (e.g. `sampling/createMessage`). The proxy forwards each\n * request to the host via these callbacks; the host's response is returned to the\n * originating upstream by the SDK.\n *\n * The `signal` parameter is the upstream's request abort signal — passing it through\n * to the host call causes the host's request to be cancelled if the upstream cancels.\n */\nexport type UpstreamServerRequestHandlers = {\n onCreateMessage?: (\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<CreateMessageResult>;\n onElicitInput?: (\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ElicitResult>;\n onListRoots?: (\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ListRootsResult>;\n};\n\ntype UpstreamClientConfig = {\n name: string;\n transport: Transport;\n onTransportError?: (error: Error) => void;\n notifications?: UpstreamNotificationHandlers;\n serverRequests?: UpstreamServerRequestHandlers;\n};\n\nexport class UpstreamClient {\n private readonly transport: Transport;\n private readonly onTransportError: (error: Error) => void;\n private readonly notificationHandlers: UpstreamNotificationHandlers;\n private readonly serverRequestHandlers: UpstreamServerRequestHandlers;\n private client: Client | null = null;\n\n constructor({\n name,\n transport,\n onTransportError,\n notifications,\n serverRequests,\n }: UpstreamClientConfig) {\n this.transport = transport;\n this.notificationHandlers = notifications ?? {};\n this.serverRequestHandlers = serverRequests ?? {};\n this.onTransportError =\n onTransportError ??\n ((error: Error) => {\n process.stderr.write(`[${name}] Upstream MCP transport error: ${error.message}\\n`);\n });\n }\n\n async connect(): Promise<void> {\n this.transport.onerror = this.onTransportError;\n this.client = new Client(\n { name: \"dynamic-discovery-mcp\", version: \"1.0.0\" },\n {\n capabilities: {\n // Declare every client-side capability the proxy may relay on behalf of the host.\n // Actual reachability of each feature depends on what the host supports — if the\n // host does not support sampling, for instance, the host call returns an error\n // which we forward back to the upstream verbatim.\n sampling: {},\n elicitation: {},\n roots: { listChanged: true },\n },\n },\n );\n\n this.registerServerRequestHandlers(this.client);\n\n if (this.notificationHandlers.onToolsListChanged !== undefined) {\n this.client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {\n await this.notificationHandlers.onToolsListChanged?.();\n });\n }\n if (this.notificationHandlers.onResourcesListChanged !== undefined) {\n this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async () => {\n await this.notificationHandlers.onResourcesListChanged?.();\n });\n }\n if (this.notificationHandlers.onResourceUpdated !== undefined) {\n this.client.setNotificationHandler(ResourceUpdatedNotificationSchema, async notification => {\n await this.notificationHandlers.onResourceUpdated?.({ uri: notification.params.uri });\n });\n }\n if (this.notificationHandlers.onPromptsListChanged !== undefined) {\n this.client.setNotificationHandler(PromptListChangedNotificationSchema, async () => {\n await this.notificationHandlers.onPromptsListChanged?.();\n });\n }\n if (this.notificationHandlers.onLogMessage !== undefined) {\n this.client.setNotificationHandler(LoggingMessageNotificationSchema, async notification => {\n await this.notificationHandlers.onLogMessage?.(notification.params);\n });\n }\n\n await this.client.connect(this.transport);\n }\n\n async setLoggingLevel(level: LoggingLevel, options?: UpstreamCallOptions): Promise<void> {\n const client = this.requireClient();\n await client.setLoggingLevel(level, options);\n }\n\n async listPrompts(options?: UpstreamCallOptions): Promise<Prompt[]> {\n const client = this.requireClient();\n const result = await client.listPrompts(undefined, options);\n return result.prompts;\n }\n\n async getPrompt(\n name: string,\n args?: Record<string, string>,\n options?: UpstreamCallOptions,\n ): Promise<GetPromptResult> {\n const client = this.requireClient();\n const params: { name: string; arguments?: Record<string, string> } = { name };\n if (args !== undefined) {\n params.arguments = args;\n }\n return client.getPrompt(params, options);\n }\n\n async complete(\n params: CompleteRequest[\"params\"],\n options?: UpstreamCallOptions,\n ): Promise<CompleteResult> {\n const client = this.requireClient();\n return client.complete(params, options);\n }\n\n /**\n * Returns the capabilities advertised by the upstream server during initialize.\n * Returns `undefined` if the client is not connected, or if the SDK has not yet\n * recorded the server's capabilities (e.g. during a partially-completed handshake).\n */\n getCapabilities(): ServerCapabilities | undefined {\n return this.client?.getServerCapabilities();\n }\n\n async listTools(options?: UpstreamCallOptions): Promise<UpstreamTool[]> {\n const client = this.requireClient();\n const result = await client.listTools(undefined, options);\n\n return result.tools.map(tool => {\n const upstreamTool: UpstreamTool = {\n name: tool.name,\n description: tool.description ?? \"\",\n inputSchema: tool.inputSchema,\n };\n\n if (tool.outputSchema !== undefined) {\n upstreamTool.outputSchema = tool.outputSchema;\n }\n\n if (tool.annotations !== undefined) {\n upstreamTool.annotations = {\n title: tool.annotations.title,\n readOnlyHint: tool.annotations.readOnlyHint,\n destructiveHint: tool.annotations.destructiveHint,\n idempotentHint: tool.annotations.idempotentHint,\n openWorldHint: tool.annotations.openWorldHint,\n };\n }\n\n return upstreamTool;\n });\n }\n\n async callTool(\n name: string,\n input: Record<string, unknown>,\n options?: UpstreamCallOptions,\n ): Promise<CallToolResult> {\n const client = this.requireClient();\n const result = await client.callTool({ name, arguments: input }, undefined, options);\n return result as CallToolResult;\n }\n\n async listResources(options?: UpstreamCallOptions): Promise<Resource[]> {\n const client = this.requireClient();\n const result = await client.listResources(undefined, options);\n return result.resources;\n }\n\n async listResourceTemplates(options?: UpstreamCallOptions): Promise<ResourceTemplate[]> {\n const client = this.requireClient();\n const result = await client.listResourceTemplates(undefined, options);\n return result.resourceTemplates;\n }\n\n async readResource(uri: string, options?: UpstreamCallOptions): Promise<ReadResourceResult> {\n const client = this.requireClient();\n return client.readResource({ uri }, options);\n }\n\n async subscribeResource(uri: string, options?: UpstreamCallOptions): Promise<void> {\n const client = this.requireClient();\n await client.subscribeResource({ uri }, options);\n }\n\n async unsubscribeResource(uri: string, options?: UpstreamCallOptions): Promise<void> {\n const client = this.requireClient();\n await client.unsubscribeResource({ uri }, options);\n }\n\n async disconnect(): Promise<void> {\n if (this.client === null) {\n return;\n }\n\n await this.client.close();\n this.client = null;\n }\n\n /**\n * Sends `notifications/roots/list_changed` to the upstream, letting it know that\n * the host's set of filesystem roots has changed.\n */\n async sendRootsListChanged(): Promise<void> {\n const client = this.requireClient();\n await client.sendRootsListChanged();\n }\n\n private registerServerRequestHandlers(client: Client): void {\n if (this.serverRequestHandlers.onCreateMessage !== undefined) {\n client.setRequestHandler(\n CreateMessageRequestSchema,\n async (request, extra): Promise<CreateMessageResult> => {\n return this.serverRequestHandlers.onCreateMessage!(request.params, {\n signal: extra.signal,\n });\n },\n );\n }\n if (this.serverRequestHandlers.onElicitInput !== undefined) {\n client.setRequestHandler(\n ElicitRequestSchema,\n async (request, extra): Promise<ElicitResult> => {\n return this.serverRequestHandlers.onElicitInput!(request.params, {\n signal: extra.signal,\n });\n },\n );\n }\n if (this.serverRequestHandlers.onListRoots !== undefined) {\n client.setRequestHandler(\n ListRootsRequestSchema,\n async (request, extra): Promise<ListRootsResult> => {\n return this.serverRequestHandlers.onListRoots!(request.params, {\n signal: extra.signal,\n });\n },\n );\n }\n }\n\n private requireClient(): Client {\n if (this.client === null) {\n throw new Error(\"Client is not connected. Call connect() first.\");\n }\n return this.client;\n }\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n UpstreamClient,\n type UpstreamNotificationHandlers,\n type UpstreamServerRequestHandlers,\n} from \"./upstream-client.js\";\n\n/**\n * Per-upstream configuration handed to {@link UpstreamRegistry.connectAll}. The registry\n * is intentionally oblivious to what the notification and server-request handlers do —\n * the caller (typically the Orchestrator) owns that logic and supplies pre-built\n * handlers that close over its own state.\n */\nexport type UpstreamConfig = {\n transport: Transport;\n onTransportError?: (error: Error) => void;\n notifications?: UpstreamNotificationHandlers;\n serverRequests?: UpstreamServerRequestHandlers;\n};\n\n/**\n * Owns the lifecycle of every connected upstream MCP. Responsibilities are narrow:\n * spin clients up, expose them by name (or as the unique sole client in single-MCP\n * mode), and tear them all down on shutdown. Catalog building, routing, notification\n * translation, and capability aggregation are deliberately not in scope here — the\n * Orchestrator composes those concerns around this registry.\n *\n * Connection is all-or-nothing: if any client fails to connect during\n * {@link connectAll}, every already-connected client is disconnected before the\n * original error is re-thrown.\n */\nexport class UpstreamRegistry {\n private readonly clients: Map<string, UpstreamClient> = new Map();\n\n async connectAll(entries: ReadonlyArray<readonly [string, UpstreamConfig]>): Promise<void> {\n try {\n for (const [mcpName, config] of entries) {\n const client = new UpstreamClient({\n name: mcpName,\n transport: config.transport,\n onTransportError: config.onTransportError,\n notifications: config.notifications,\n serverRequests: config.serverRequests,\n });\n await client.connect();\n this.clients.set(mcpName, client);\n }\n } catch (error) {\n await this.disconnectAll();\n throw error;\n }\n }\n\n /**\n * Connects a single additional upstream. Unlike {@link connectAll}, a failure here\n * leaves any other connected clients untouched — the caller (typically the\n * Orchestrator's `loadMcp` pipeline) needs that isolation because other lazy MCPs\n * may have already been promoted to loaded, or eager MCPs are still healthy.\n *\n * Throws if `mcpName` is already in the registry; callers should check beforehand\n * (the orchestrator handles the idempotency-success case before reaching here).\n */\n async connectOne(mcpName: string, config: UpstreamConfig): Promise<UpstreamClient> {\n if (this.clients.has(mcpName)) {\n throw new Error(`UpstreamRegistry: \"${mcpName}\" is already connected`);\n }\n const client = new UpstreamClient({\n name: mcpName,\n transport: config.transport,\n onTransportError: config.onTransportError,\n notifications: config.notifications,\n serverRequests: config.serverRequests,\n });\n await client.connect();\n this.clients.set(mcpName, client);\n return client;\n }\n\n /**\n * Disconnects and removes a single upstream. Used by `loadMcp` to roll back a\n * partially-loaded MCP when a post-connect catalog query fails. No-op if the name\n * is not present.\n */\n async deleteOne(mcpName: string): Promise<void> {\n const client = this.clients.get(mcpName);\n if (client === undefined) return;\n this.clients.delete(mcpName);\n await client.disconnect();\n }\n\n get(mcpName: string): UpstreamClient | undefined {\n return this.clients.get(mcpName);\n }\n\n /**\n * Returns the sole connected client. Used by single-MCP (`--`) mode where the\n * Orchestrator guarantees there is exactly one upstream. Returns undefined when\n * zero or more than one client is connected.\n */\n sole(): UpstreamClient | undefined {\n if (this.clients.size !== 1) return undefined;\n return this.clients.values().next().value;\n }\n\n names(): readonly string[] {\n return [...this.clients.keys()];\n }\n\n entries(): IterableIterator<[string, UpstreamClient]> {\n return this.clients.entries();\n }\n\n size(): number {\n return this.clients.size;\n }\n\n async disconnectAll(): Promise<void> {\n const disconnections = [...this.clients.values()].map(client => client.disconnect());\n await Promise.all(disconnections);\n this.clients.clear();\n }\n}\n","import process from \"node:process\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n CompleteRequestSchema,\n type CompleteRequest,\n type CompleteResult,\n type CreateMessageRequest,\n type CreateMessageResult,\n type ElicitRequest,\n type ElicitResult,\n GetPromptRequestSchema,\n type GetPromptResult,\n ListPromptsRequestSchema,\n type ListPromptsResult,\n ListResourcesRequestSchema,\n type ListResourcesResult,\n ListResourceTemplatesRequestSchema,\n type ListResourceTemplatesResult,\n type ListRootsRequest,\n type ListRootsResult,\n ListToolsRequestSchema,\n type LoggingLevel,\n type LoggingMessageNotification,\n type Prompt,\n ReadResourceRequestSchema,\n type ReadResourceResult,\n type Resource,\n type ResourceTemplate,\n RootsListChangedNotificationSchema,\n type ServerCapabilities,\n SetLevelRequestSchema,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\nimport packageJson from \"../../package.json\" with { type: \"json\" };\nimport type { ToolCatalog } from \"./tool-catalog.js\";\n\nexport type ProgressEvent = {\n progress: number;\n total?: number;\n message?: string;\n};\n\n/**\n * Per-call options forwarded by the proxy server's request handlers to the orchestrator.\n *\n * - `signal`: propagates host-side cancellation through to the upstream call. When the\n * host cancels its incoming request, the SDK client emits `notifications/cancelled`\n * to the upstream.\n * - `onprogress`: invoked when the upstream emits a `notifications/progress` for the\n * in-flight call. The proxy server uses this to translate upstream progress events\n * into host-facing notifications under the host's original progress token.\n */\nexport type ProxyCallOptions = {\n signal?: AbortSignal;\n onprogress?: (progress: ProgressEvent) => void;\n};\n\nexport type ToolCaller = (\n name: string,\n input: Record<string, unknown>,\n options?: ProxyCallOptions,\n) => Promise<CallToolResult>;\n\nexport type ResourceCallbacks = {\n listResources: () => Resource[];\n listResourceTemplates: () => ResourceTemplate[];\n readResource: (uri: string, options?: ProxyCallOptions) => Promise<ReadResourceResult>;\n subscribeResource: (uri: string, options?: ProxyCallOptions) => Promise<void>;\n unsubscribeResource: (uri: string, options?: ProxyCallOptions) => Promise<void>;\n};\n\nexport type PromptCallbacks = {\n listPrompts: () => Prompt[];\n getPrompt: (\n name: string,\n args?: Record<string, string>,\n options?: ProxyCallOptions,\n ) => Promise<GetPromptResult>;\n};\n\nexport type CompletionCallback = (\n params: CompleteRequest[\"params\"],\n options?: ProxyCallOptions,\n) => Promise<CompleteResult>;\n\nexport type LoggingSetLevelCallback = (\n level: LoggingLevel,\n options?: ProxyCallOptions,\n) => Promise<void>;\n\n/**\n * Result returned by {@link LoadMcpCallback}. Kept loose (a plain JSON value) here so\n * the ProxyServer does not depend on the orchestrator's `LoadMcpResult` type — the\n * server just serializes whatever the orchestrator returns into the tool response.\n */\nexport type LoadMcpCallback = (mcpName: string) => Promise<unknown>;\n\nexport type LogMessageParams = LoggingMessageNotification[\"params\"];\n\ntype ProxyServerConfig = {\n /**\n * Function returning the current tool catalog. A function (rather than a static value)\n * lets the proxy regenerate `discover_tool`'s description on the fly when an upstream\n * emits `notifications/tools/list_changed`.\n */\n catalog: () => ToolCatalog;\n callTool: ToolCaller;\n /**\n * Aggregated capabilities to advertise to the host during `initialize`. Built by\n * `aggregateCapabilities()` from the union of all upstream capabilities. The proxy\n * always advertises `tools` regardless of upstream support.\n */\n capabilities: ServerCapabilities;\n /**\n * Resource access callbacks. Required when `capabilities.resources` is advertised;\n * otherwise the resource request handlers are not registered.\n */\n resources?: ResourceCallbacks;\n /**\n * Prompt access callbacks. Required when `capabilities.prompts` is advertised;\n * otherwise the prompt request handlers are not registered.\n */\n prompts?: PromptCallbacks;\n /**\n * Completion routing callback. Required when `capabilities.completions` is advertised;\n * otherwise the completion request handler is not registered.\n */\n complete?: CompletionCallback;\n /**\n * Logging set-level callback. Required when `capabilities.logging` is advertised;\n * otherwise the `logging/setLevel` request handler is not registered.\n */\n setLoggingLevel?: LoggingSetLevelCallback;\n /**\n * Invoked when the host emits `notifications/roots/list_changed`. The proxy will\n * call this so the orchestrator can broadcast the change to all upstreams that\n * declared the `roots` client capability to us.\n */\n onRootsListChanged?: () => void | Promise<void>;\n /**\n * Optional dynamic-discovery callback. When provided, the `load_mcp` meta-tool is\n * registered alongside `discover_tool` and `use_tool`. Absent in single-MCP mode\n * and in config-file mode with no `description` fields. See SPEC.md § \"Dynamic\n * Discovery\" and § \"Tools > load_mcp\".\n */\n loadMcp?: LoadMcpCallback;\n};\n\nconst DISCOVER_TOOL_NAME = \"discover_tool\";\nconst USE_TOOL_NAME = \"use_tool\";\nconst LOAD_MCP_NAME = \"load_mcp\";\n\nconst USE_TOOL_DESCRIPTION =\n \"Use a tool that was previously discovered with the discover_tool tool.\";\n\nconst LOAD_MCP_DESCRIPTION =\n \"Load a previously-deferred MCP server so that its tools, resources, and prompts become available. Pass the server name as shown in the <mcp_servers> block of the discover_tool description. Loading is permanent for the remainder of this session.\";\n\nconst DISCOVER_TOOL_INPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n tool_name: { type: \"string\" as const },\n },\n required: [\"tool_name\"],\n};\n\nconst USE_TOOL_INPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n tool_name: { type: \"string\" as const },\n tool_input: { type: \"object\" as const, additionalProperties: true, default: {} },\n },\n required: [\"tool_name\"],\n};\n\nconst LOAD_MCP_INPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n mcp_name: { type: \"string\" as const },\n },\n required: [\"mcp_name\"],\n};\n\nconst DiscoverToolArgsSchema = z.object({ tool_name: z.string() });\nconst UseToolArgsSchema = z.object({\n tool_name: z.string(),\n tool_input: z.record(z.string(), z.unknown()).default({}),\n});\nconst LoadMcpArgsSchema = z.object({ mcp_name: z.string() });\n\nexport class ProxyServer {\n private readonly catalog: () => ToolCatalog;\n private readonly callTool: ToolCaller;\n private readonly capabilities: ServerCapabilities;\n private readonly resources: ResourceCallbacks | undefined;\n private readonly prompts: PromptCallbacks | undefined;\n private readonly complete: CompletionCallback | undefined;\n private readonly setLoggingLevelCallback: LoggingSetLevelCallback | undefined;\n private readonly onRootsListChangedCallback: (() => void | Promise<void>) | undefined;\n private readonly loadMcpCallback: LoadMcpCallback | undefined;\n private sdkServer: Server | null = null;\n\n constructor({\n catalog,\n callTool,\n capabilities,\n resources,\n prompts,\n complete,\n setLoggingLevel,\n onRootsListChanged,\n loadMcp,\n }: ProxyServerConfig) {\n this.catalog = catalog;\n this.callTool = callTool;\n this.capabilities = capabilities;\n this.resources = resources;\n this.prompts = prompts;\n this.complete = complete;\n this.setLoggingLevelCallback = setLoggingLevel;\n this.onRootsListChangedCallback = onRootsListChanged;\n this.loadMcpCallback = loadMcp;\n }\n\n buildServer(): Server {\n const server = new Server(\n {\n name: \"dynamic-discovery-mcp\",\n version: packageJson.version,\n },\n {\n capabilities: this.capabilities,\n },\n );\n\n this.registerToolHandlers(server);\n if (this.capabilities.resources !== undefined && this.resources !== undefined) {\n this.registerResourceHandlers(server, this.resources);\n }\n if (this.capabilities.prompts !== undefined && this.prompts !== undefined) {\n this.registerPromptHandlers(server, this.prompts);\n }\n if (this.capabilities.completions !== undefined && this.complete !== undefined) {\n this.registerCompletionHandler(server, this.complete);\n }\n if (this.capabilities.logging !== undefined && this.setLoggingLevelCallback !== undefined) {\n this.registerLoggingHandler(server, this.setLoggingLevelCallback);\n }\n if (this.onRootsListChangedCallback !== undefined) {\n const callback = this.onRootsListChangedCallback;\n server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {\n await callback();\n });\n }\n\n this.sdkServer = server;\n return server;\n }\n\n /**\n * Forwards an upstream-initiated `sampling/createMessage` request to the host. The\n * upstream's abort signal is threaded through so cancellation by the upstream\n * propagates to the host.\n */\n async forwardCreateMessage(\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<CreateMessageResult> {\n const server = this.requireSdkServer();\n return server.createMessage(params, options);\n }\n\n /**\n * Forwards an upstream-initiated `elicitation/create` request to the host.\n */\n async forwardElicitInput(\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ElicitResult> {\n const server = this.requireSdkServer();\n return server.elicitInput(params, options);\n }\n\n /**\n * Forwards an upstream-initiated `roots/list` request to the host.\n */\n async forwardListRoots(\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ListRootsResult> {\n const server = this.requireSdkServer();\n return server.listRoots(params, options);\n }\n\n private requireSdkServer(): Server {\n if (this.sdkServer === null) {\n throw new Error(\"ProxyServer is not built. Call buildServer() before forwarding requests.\");\n }\n return this.sdkServer;\n }\n\n async start(): Promise<void> {\n const server = this.buildServer();\n const transport = new StdioServerTransport();\n process.stderr.write(\"Starting dynamic-discovery-mcp server over stdio\\n\");\n await server.connect(transport);\n }\n\n /**\n * Notifies the host that the discover_tool description has changed because an upstream\n * emitted `notifications/tools/list_changed`. The host should re-fetch the tools list\n * to pick up the regenerated catalog. Silently no-ops if `buildServer()` has not been\n * called yet.\n */\n async sendToolListChanged(): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendToolListChanged();\n }\n }\n\n /**\n * Notifies the host that the proxy's aggregated resource list has changed. Silently\n * no-ops if `buildServer()` has not been called yet. Errors propagate.\n */\n async sendResourceListChanged(): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendResourceListChanged();\n }\n }\n\n /**\n * Notifies the host that a specific subscribed resource has changed. Silently no-ops\n * if `buildServer()` has not been called yet.\n */\n async sendResourceUpdated(params: { uri: string }): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendResourceUpdated(params);\n }\n }\n\n /**\n * Notifies the host that the proxy's aggregated prompt list has changed. Silently\n * no-ops if `buildServer()` has not been called yet.\n */\n async sendPromptListChanged(): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendPromptListChanged();\n }\n }\n\n /**\n * Builds per-call options for a request handler. Extracts the host's\n * `progressToken` from `_meta` (if any) and wires an `onprogress` callback that\n * re-emits progress notifications back to the host under that same token. This\n * is the single seam where progress translation lives — every forward-direction\n * handler routes through here.\n */\n private buildCallOptions(\n request: { params: { _meta?: { progressToken?: string | number } } },\n extra: {\n signal: AbortSignal;\n sendNotification: (notification: {\n method: string;\n params?: Record<string, unknown>;\n }) => Promise<void>;\n },\n ): ProxyCallOptions {\n const options: ProxyCallOptions = { signal: extra.signal };\n const progressToken = request.params._meta?.progressToken;\n if (progressToken !== undefined) {\n options.onprogress = progress => {\n void extra.sendNotification({\n method: \"notifications/progress\",\n params: {\n progressToken,\n progress: progress.progress,\n total: progress.total,\n message: progress.message,\n },\n });\n };\n }\n return options;\n }\n\n private registerToolHandlers(server: Server): void {\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n type ListedTool = {\n name: string;\n description: string;\n inputSchema: { type: \"object\"; properties: Record<string, unknown>; required: string[] };\n };\n const tools: ListedTool[] = [\n {\n name: DISCOVER_TOOL_NAME,\n description: this.catalog().discoverToolDescription,\n inputSchema: DISCOVER_TOOL_INPUT_SCHEMA,\n },\n {\n name: USE_TOOL_NAME,\n description: USE_TOOL_DESCRIPTION,\n inputSchema: USE_TOOL_INPUT_SCHEMA,\n },\n ];\n if (this.loadMcpCallback !== undefined) {\n tools.push({\n name: LOAD_MCP_NAME,\n description: LOAD_MCP_DESCRIPTION,\n inputSchema: LOAD_MCP_INPUT_SCHEMA,\n });\n }\n return { tools };\n });\n\n server.setRequestHandler(\n CallToolRequestSchema,\n async (request, extra): Promise<CallToolResult> => {\n const { name, arguments: rawArgs } = request.params;\n const catalog = this.catalog();\n\n if (name === DISCOVER_TOOL_NAME) {\n const args = DiscoverToolArgsSchema.parse(rawArgs ?? {});\n return {\n content: [{ type: \"text\", text: catalog.getToolDetails(args.tool_name) }],\n };\n }\n\n if (name === USE_TOOL_NAME) {\n const args = UseToolArgsSchema.parse(rawArgs ?? {});\n if (!catalog.tools.has(args.tool_name)) {\n return {\n content: [{ type: \"text\", text: catalog.getToolDetails(args.tool_name) }],\n };\n }\n return await this.callTool(\n args.tool_name,\n args.tool_input,\n this.buildCallOptions(request, extra),\n );\n }\n\n if (name === LOAD_MCP_NAME && this.loadMcpCallback !== undefined) {\n const args = LoadMcpArgsSchema.parse(rawArgs ?? {});\n try {\n const result = await this.loadMcpCallback(args.mcp_name);\n return {\n // The structured payload is JSON-serialized into a text block. We also\n // populate `structuredContent` so MCP clients that prefer typed data can\n // consume the same response without parsing the text body.\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n structuredContent: result as Record<string, unknown>,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: message }],\n };\n }\n }\n\n return {\n isError: true,\n content: [{ type: \"text\", text: `Unknown tool: \"${name}\"` }],\n };\n },\n );\n }\n\n private registerResourceHandlers(server: Server, callbacks: ResourceCallbacks): void {\n server.setRequestHandler(\n ListResourcesRequestSchema,\n async (): Promise<ListResourcesResult> => ({\n resources: callbacks.listResources(),\n }),\n );\n\n server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async (): Promise<ListResourceTemplatesResult> => ({\n resourceTemplates: callbacks.listResourceTemplates(),\n }),\n );\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request, extra): Promise<ReadResourceResult> => {\n return callbacks.readResource(request.params.uri, this.buildCallOptions(request, extra));\n },\n );\n\n server.setRequestHandler(SubscribeRequestSchema, async (request, extra) => {\n await callbacks.subscribeResource(request.params.uri, this.buildCallOptions(request, extra));\n return {};\n });\n\n server.setRequestHandler(UnsubscribeRequestSchema, async (request, extra) => {\n await callbacks.unsubscribeResource(\n request.params.uri,\n this.buildCallOptions(request, extra),\n );\n return {};\n });\n }\n\n private registerPromptHandlers(server: Server, callbacks: PromptCallbacks): void {\n server.setRequestHandler(\n ListPromptsRequestSchema,\n async (): Promise<ListPromptsResult> => ({\n prompts: callbacks.listPrompts(),\n }),\n );\n\n server.setRequestHandler(\n GetPromptRequestSchema,\n async (request, extra): Promise<GetPromptResult> => {\n return callbacks.getPrompt(\n request.params.name,\n request.params.arguments,\n this.buildCallOptions(request, extra),\n );\n },\n );\n }\n\n private registerCompletionHandler(server: Server, callback: CompletionCallback): void {\n server.setRequestHandler(\n CompleteRequestSchema,\n async (request, extra): Promise<CompleteResult> => {\n return callback(request.params, this.buildCallOptions(request, extra));\n },\n );\n }\n\n private registerLoggingHandler(server: Server, callback: LoggingSetLevelCallback): void {\n server.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {\n await callback(request.params.level, this.buildCallOptions(request, extra));\n return {};\n });\n }\n\n /**\n * Forwards a log message from an upstream MCP to the host. Silently no-ops if\n * `buildServer()` has not been called yet.\n */\n async sendLoggingMessage(params: LogMessageParams): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendLoggingMessage(params);\n }\n }\n}\n","import { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\n\ninterface StdioTransportConfig {\n transport: \"stdio\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n // Tolerated but unused by the factory. Present so a Zod-validated config entry can be\n // forwarded here without an intermediate destructure; the field is consumed by the\n // orchestrator's lazy-loading logic, not by transport construction.\n description?: string;\n}\n\ninterface StreamableHttpTransportConfig {\n transport: \"streamable-http\";\n url: string;\n headers?: Record<string, string>;\n description?: string;\n}\n\ninterface SseTransportConfig {\n transport: \"sse\";\n url: string;\n headers?: Record<string, string>;\n description?: string;\n}\n\nexport type McpTransportConfig =\n | StdioTransportConfig\n | StreamableHttpTransportConfig\n | SseTransportConfig;\n\nexport function createTransport(config: McpTransportConfig): Transport {\n switch (config.transport) {\n case \"stdio\":\n return new StdioClientTransport({\n command: config.command,\n args: config.args,\n env: config.env,\n });\n\n case \"streamable-http\":\n return new StreamableHTTPClientTransport(\n new URL(config.url),\n config.headers ? { requestInit: { headers: config.headers } } : undefined,\n );\n\n case \"sse\":\n return new SSEClientTransport(\n new URL(config.url),\n config.headers ? { requestInit: { headers: config.headers } } : undefined,\n );\n\n default: {\n const _exhaustive: never = config;\n return _exhaustive;\n }\n }\n}\n","import { cli } from \"./cli.js\";\nimport process from \"node:process\";\n\nasync function main() {\n cli.parse(process.argv);\n}\n\nmain();\n"],"mappings":"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","names":["import_node_process","import_node_process","import_stdio","import_node_fs","import_node_path","import_node_process","process","dotenv","process","parseYaml","import_zod","import_node_process","mcpName","mcpName","mcpName","description","mcpName","import_node_process","process","mcpName","description","mcpName","process","import_node_process","import_types","import_zod","process","import_stdio","mcpName","process","chalk","figlet","process","import_node_process","process"]}
1
+ {"version":3,"sources":["../src/cli.ts","../package.json","../src/auth/errors.ts","../src/auth/keychain-store.ts","../src/auth/types.ts","../src/auth/oauth-provider.ts","../src/auth/login.ts","../src/config/schema.ts","../src/config/loader.ts","../src/config/env-sources.ts","../src/config/interpolate.ts","../src/config/json-schema.ts","../src/auth/browser.ts","../src/auth/callback-server.ts","../src/auth/logout.ts","../src/diagnostics/list.ts","../src/diagnostics/format.ts","../src/diagnostics/test.ts","../src/proxy/transport-factory.ts","../src/proxy/upstream-client.ts","../src/proxy/index.ts","../src/proxy/orchestrator.ts","../src/proxy/capability-aggregator.ts","../src/proxy/lazy-registry.ts","../src/proxy/notification-forwarder.ts","../src/proxy/prompt-router.ts","../src/proxy/resource-router.ts","../src/proxy/tool-catalog.ts","../src/proxy/upstream-registry.ts","../src/proxy/server.ts","../src/scaffold/init.ts","../src/scaffold/format.ts","../src/scaffold/add.ts","../src/index.ts"],"sourcesContent":["import process from \"node:process\";\nimport { Command } from \"commander\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport figlet from \"figlet\";\nimport chalk from \"chalk\";\nimport { login, logout } from \"./auth/index.js\";\nimport { list, test } from \"./diagnostics/index.js\";\nimport { startProxy, startProxyFromConfig } from \"./proxy/index.js\";\nimport { add, init, type TransportKind } from \"./scaffold/index.js\";\n\nconst cliBanner = chalk.bold.magentaBright(\n figlet.textSync(\"DYNAMIC MCP\", {\n font: \"Sub-Zero\",\n horizontalLayout: \"fitted\",\n verticalLayout: \"fitted\",\n }),\n);\n\nexport const cli = new Command(packageJson.name)\n .description(packageJson.description)\n .version(packageJson.version)\n .addHelpText(\"beforeAll\", cliBanner)\n .addHelpText(\n \"after\",\n \"\\nExamples:\\n\" +\n \" dynmcp -- npx -y chrome-devtools-mcp@latest\\n\" +\n \" dynmcp --config ./mcp.json\\n\" +\n \" dynmcp init\\n\" +\n \" dynmcp add filesystem --command npx --arg -y --arg @modelcontextprotocol/server-filesystem --arg /tmp\\n\" +\n \" dynmcp add github --transport streamable-http --url https://api.githubcopilot.com/mcp\\n\" +\n \" dynmcp ls\\n\" +\n \" dynmcp test github\\n\" +\n \" dynmcp login github\\n\" +\n \" dynmcp logout github\\n\",\n )\n .option(\"-c, --config <path>\", \"Path to config file (JSON or YAML)\")\n .option(\"-e, --env <path>\", \"Path to a .env file for environment variable interpolation\")\n .allowExcessArguments(true)\n .passThroughOptions(true)\n .action(async (_options, cmd) => {\n const separatorIndex = process.argv.indexOf(\"--\");\n const configPath = cmd.opts().config as string | undefined;\n const envFilePath = cmd.opts().env as string | undefined;\n\n if (separatorIndex !== -1) {\n const [command, ...args] = process.argv.slice(separatorIndex + 1);\n\n if (command === undefined) {\n process.stderr.write(\n \"dynmcp: no upstream command provided after --.\\n\" +\n \"Usage: dynmcp -- <command> [args...]\\n\",\n );\n process.exit(1);\n }\n\n try {\n await startProxy(command, args);\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n return;\n }\n\n try {\n await startProxyFromConfig({ configPath, envFilePath });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n });\n\ncli\n .command(\"init\")\n .description(\"Write a starter config file (mcp.json by default) in the current directory.\")\n .option(\"--path <path>\", \"Explicit target path (extension determines format).\")\n .option(\"--yaml\", \"Write mcp.yaml instead of mcp.json (ignored if --path is set).\")\n .option(\"--force\", \"Overwrite an existing file.\")\n .action((options: { path?: string; yaml?: boolean; force?: boolean }) => {\n try {\n init({\n ...(options.path !== undefined ? { path: options.path } : {}),\n ...(options.yaml === true ? { yaml: true } : {}),\n ...(options.force === true ? { force: true } : {}),\n });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n });\n\nconst collectRepeatable = (value: string, previous: string[]): string[] => [...previous, value];\n\ncli\n .command(\"add <name>\")\n .description(\"Insert a new MCP entry into the resolved config file.\")\n .option(\n \"-t, --transport <transport>\",\n \"Transport: stdio | streamable-http | sse (default: stdio).\",\n \"stdio\",\n )\n .option(\"-c, --config <path>\", \"Path to config file (otherwise auto-discovered).\")\n .option(\"--description <text>\", \"Per-entry description; presence makes the entry lazy.\")\n .option(\"--command <cmd>\", \"(stdio) Command to spawn for the upstream MCP.\")\n .option(\n \"--arg <arg>\",\n \"(stdio) Repeatable positional argument passed after --command.\",\n collectRepeatable,\n [] as string[],\n )\n .option(\n \"--env <KEY=VAL>\",\n \"(stdio) Repeatable env var for the spawned process.\",\n collectRepeatable,\n [] as string[],\n )\n .option(\"--url <url>\", \"(http/sse) Endpoint URL.\")\n .option(\n \"--header <header>\",\n '(http/sse) Repeatable \"Name: Value\" header.',\n collectRepeatable,\n [] as string[],\n )\n .option(\"--client-id <id>\", \"(http/sse) Pre-registered OAuth client_id (skips DCR).\")\n .option(\"--client-secret <secret>\", \"(http/sse) Pre-registered OAuth client_secret.\")\n .option(\"--scope <scope>\", \"(http/sse) OAuth scope to request.\")\n .option(\"--force\", \"Overwrite an existing entry with the same name.\")\n .action(\n (\n name: string,\n options: {\n transport: string;\n config?: string;\n description?: string;\n command?: string;\n arg: string[];\n env: string[];\n url?: string;\n header: string[];\n clientId?: string;\n clientSecret?: string;\n scope?: string;\n force?: boolean;\n },\n ) => {\n try {\n const transport = options.transport as TransportKind;\n if (transport !== \"stdio\" && transport !== \"streamable-http\" && transport !== \"sse\") {\n throw new Error(\n `Invalid --transport '${options.transport}'. Must be one of: stdio, streamable-http, sse.`,\n );\n }\n add({\n name,\n transport,\n ...(options.config !== undefined ? { configPath: options.config } : {}),\n ...(options.force === true ? { force: true } : {}),\n ...(options.description !== undefined ? { description: options.description } : {}),\n ...(options.command !== undefined ? { command: options.command } : {}),\n ...(options.arg.length > 0 ? { args: options.arg } : {}),\n ...(options.env.length > 0 ? { envVars: options.env } : {}),\n ...(options.url !== undefined ? { url: options.url } : {}),\n ...(options.header.length > 0 ? { headers: options.header } : {}),\n ...(options.clientId !== undefined ? { clientId: options.clientId } : {}),\n ...(options.clientSecret !== undefined ? { clientSecret: options.clientSecret } : {}),\n ...(options.scope !== undefined ? { scope: options.scope } : {}),\n });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n },\n );\n\ncli\n .command(\"login <name>\")\n .description(\"Run the OAuth authorization-code flow for an upstream MCP and store tokens.\")\n .option(\"-c, --config <path>\", \"Path to config file (JSON or YAML)\")\n .option(\"-e, --env <path>\", \"Path to a .env file for environment variable interpolation\")\n .action(async (name: string, options: { config?: string; env?: string }) => {\n try {\n await login({\n mcpName: name,\n ...(options.config !== undefined ? { configPath: options.config } : {}),\n ...(options.env !== undefined ? { envFilePath: options.env } : {}),\n });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n });\n\ncli\n .command(\"logout <name>\")\n .description(\"Delete the OAuth keychain entry for an upstream MCP.\")\n .option(\"-c, --config <path>\", \"Path to config file (JSON or YAML)\")\n .option(\"-e, --env <path>\", \"Path to a .env file for environment variable interpolation\")\n .action(async (name: string, options: { config?: string; env?: string }) => {\n try {\n await logout({\n mcpName: name,\n ...(options.config !== undefined ? { configPath: options.config } : {}),\n ...(options.env !== undefined ? { envFilePath: options.env } : {}),\n });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n });\n\ncli\n .command(\"ls\")\n .description(\"List configured upstream MCPs with transport, mode, endpoint, and auth status.\")\n .option(\"-c, --config <path>\", \"Path to config file (JSON or YAML)\")\n .option(\"-e, --env <path>\", \"Path to a .env file for environment variable interpolation\")\n .option(\"--json\", \"Emit JSON instead of the aligned text table\")\n .action(async (options: { config?: string; env?: string; json?: boolean }) => {\n try {\n await list({\n ...(options.config !== undefined ? { configPath: options.config } : {}),\n ...(options.env !== undefined ? { envFilePath: options.env } : {}),\n ...(options.json === true ? { json: true } : {}),\n });\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n });\n\ncli\n .command(\"test [name]\")\n .description(\"Probe one or all configured upstream MCPs and print their discovered catalogs.\")\n .option(\"-c, --config <path>\", \"Path to config file (JSON or YAML)\")\n .option(\"-e, --env <path>\", \"Path to a .env file for environment variable interpolation\")\n .option(\"--json\", \"Emit JSON instead of the formatted text output\")\n .option(\"--timeout <ms>\", \"Per-MCP timeout in milliseconds (default: 15000)\", v => Number(v))\n .action(\n async (\n name: string | undefined,\n options: { config?: string; env?: string; json?: boolean; timeout?: number },\n ) => {\n try {\n const exitCode = await test({\n ...(name !== undefined ? { mcpName: name } : {}),\n ...(options.config !== undefined ? { configPath: options.config } : {}),\n ...(options.env !== undefined ? { envFilePath: options.env } : {}),\n ...(options.json === true ? { json: true } : {}),\n ...(options.timeout !== undefined && !Number.isNaN(options.timeout)\n ? { timeoutMs: options.timeout }\n : {}),\n });\n if (exitCode !== 0) process.exit(exitCode);\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n }\n },\n );\n","{\n \"name\": \"dynmcp\",\n \"version\": \"0.6.0\",\n \"description\": \"Dynamic MCP context management tool for AI MCP-enabled agents and clients.\",\n \"author\": \"Brandon Burrus <brandon@burrus.io>\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"homepage\": \"https://dynamicmcp.tools\",\n \"keywords\": [\n \"mcp\",\n \"model-context-protocol\",\n \"ai\",\n \"agent\",\n \"proxy\",\n \"dynamic\",\n \"discovery\",\n \"tools\",\n \"llm\",\n \"cli\"\n ],\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/brandonburrus/dynamic-discovery-mcp.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/brandonburrus/dynamic-discovery-mcp/issues\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"dynmcp\": \"./dist/index.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"generate:schema\": \"tsx scripts/generate-schema.ts\",\n \"build\": \"tsup\",\n \"dev\": \"tsx src/index.ts\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"biome lint .\",\n \"format\": \"biome format --write .\",\n \"check\": \"biome check --write .\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"prepare\": \"husky\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.29.0\",\n \"@napi-rs/keyring\": \"^1.3.0\",\n \"boxen\": \"^8.0.1\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^14.0.3\",\n \"dotenv\": \"^17.4.2\",\n \"enquirer\": \"^2.4.1\",\n \"fastmcp\": \"^4.0.1\",\n \"figlet\": \"^1.11.0\",\n \"figures\": \"^6.1.0\",\n \"yaml\": \"^2.9.0\",\n \"zod\": \"^4.4.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.4.15\",\n \"@commitlint/cli\": \"^21.0.1\",\n \"@commitlint/config-conventional\": \"^21.0.1\",\n \"@types/node\": \"^25.9.0\",\n \"@vitest/coverage-v8\": \"^4.1.6\",\n \"husky\": \"^9.1.7\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.22.2\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.6\"\n }\n}\n","/**\n * Thrown by {@link ProxyOAuthProvider} when the SDK would otherwise redirect the user\n * to an authorization URL or request a PKCE verifier we don't have. The proxy runs\n * over stdio and cannot drive an interactive auth flow; the user must instead run\n * `dynmcp login <name>` from a terminal.\n *\n * The error message is the actionable instruction returned to the agent / surfaced on\n * stderr by callers. See SPEC.md § \"Upstream OAuth > Proxy Runtime Behavior\".\n */\nexport class AuthRequiredError extends Error {\n readonly mcpName: string;\n\n constructor(mcpName: string) {\n super(\n `Upstream MCP \"${mcpName}\" requires authorization. ` +\n `Run \\`dynmcp login ${mcpName}\\` from your terminal, then retry.`,\n );\n this.name = \"AuthRequiredError\";\n this.mcpName = mcpName;\n }\n}\n\n/**\n * Returns `true` if `error` is an {@link AuthRequiredError} either directly or as the\n * `cause` of a wrapping error (the MCP SDK wraps provider exceptions inside\n * `UnauthorizedError` during the {@link auth} orchestration). Used by the orchestrator\n * to exempt auth-required failures from the lazy-load retry budget.\n */\nexport function isAuthRequiredError(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; depth < 8 && current !== null && current !== undefined; depth += 1) {\n if (current instanceof AuthRequiredError) return true;\n if (current instanceof Error && current.name === \"AuthRequiredError\") return true;\n if (current instanceof Error) {\n current = current.cause;\n continue;\n }\n return false;\n }\n return false;\n}\n","import { Entry } from \"@napi-rs/keyring\";\nimport { KEYCHAIN_BLOB_VERSION, type KeychainBlob } from \"./types.js\";\n\n/**\n * Service name used for every entry written by `dynmcp`. Inspecting the OS keychain\n * UI, all proxy-managed credentials sort together under this name.\n */\nexport const KEYCHAIN_SERVICE = \"dynmcp\";\n\n/**\n * Computes the keychain account identifier from an MCP name and its configured\n * upstream URL. Including the resource server origin guarantees that re-pointing an\n * MCP at a new URL in config does not silently authenticate against stale tokens —\n * the entry won't be found and a fresh `dynmcp login` is required.\n *\n * @param mcpName the MCP name as configured under `mcp.<name>` in the config file\n * @param serverUrl the configured upstream URL (origin is extracted; path is ignored)\n * @throws {TypeError} if `serverUrl` cannot be parsed as a URL\n */\nexport function buildKeychainAccount(mcpName: string, serverUrl: string): string {\n const origin = new URL(serverUrl).origin;\n return `${mcpName}:${origin}`;\n}\n\n/**\n * Type-safe wrapper around a single keychain entry. Each upstream MCP that requires\n * OAuth has at most one {@link KeychainStore} backing it; the store reads and writes\n * the entire {@link KeychainBlob} atomically so refreshing tokens never leaves a\n * partially-updated record on disk.\n *\n * The {@link Entry} from `@napi-rs/keyring` performs blocking native calls, so prefer\n * batching reads at the start of a request (the {@link ProxyOAuthProvider} does this\n * implicitly via the SDK's `auth()` flow). Tests can construct stores against a\n * different `service` to avoid clobbering the real keychain.\n */\nexport class KeychainStore {\n private readonly entry: Entry;\n\n constructor(\n public readonly mcpName: string,\n public readonly serverUrl: string,\n service: string = KEYCHAIN_SERVICE,\n ) {\n this.entry = new Entry(service, buildKeychainAccount(mcpName, serverUrl));\n }\n\n /**\n * Returns the parsed blob or `undefined` if no entry exists. Entries written under\n * a different {@link KeychainBlob.version} are treated as absent — the caller must\n * re-authenticate. Malformed JSON also returns `undefined` (corrupt entries are not\n * surfaced as errors; recovery is the same: re-auth).\n */\n get(): KeychainBlob | undefined {\n const raw = this.entry.getPassword();\n if (raw === null) return undefined;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n\n if (!isCurrentVersionBlob(parsed)) {\n return undefined;\n }\n\n return parsed;\n }\n\n /**\n * Persists the blob atomically. Caller must construct a complete {@link\n * KeychainBlob} — partial updates are not supported. To mutate, call {@link get},\n * spread, and pass the result back to {@link set}.\n */\n set(blob: KeychainBlob): void {\n const stamped: KeychainBlob = { ...blob, version: KEYCHAIN_BLOB_VERSION };\n this.entry.setPassword(JSON.stringify(stamped));\n }\n\n /**\n * Deletes the entry. Returns `true` if an entry was present and removed, `false`\n * if there was nothing to delete. Idempotent: callers should treat both outcomes\n * as success (a no-op delete is not an error).\n */\n delete(): boolean {\n return this.entry.deletePassword();\n }\n}\n\n/**\n * Discriminates {@link KeychainBlob} from any other JSON value found in the keychain.\n * Only the version sentinel is checked — full structural validation would add code\n * surface for very little benefit since we control every write path.\n */\nfunction isCurrentVersionBlob(value: unknown): value is KeychainBlob {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"version\" in value &&\n (value as { version: unknown }).version === KEYCHAIN_BLOB_VERSION\n );\n}\n","/**\n * Subset of RFC 8414 authorization-server metadata that the proxy persists alongside\n * tokens. Discovered during `dynmcp login` and cached so subsequent refreshes don't\n * have to re-do RFC 9728 + RFC 8414 discovery on every connect.\n *\n * `revocation_endpoint` is intentionally omitted in v1 — token revocation on logout\n * is a non-goal. The endpoint can be added in a future blob version once revocation\n * support lands (bump `KEYCHAIN_BLOB_VERSION` and add migration logic).\n */\nexport type AuthorizationServerSnapshot = {\n issuer: string;\n authorization_endpoint: string;\n token_endpoint: string;\n registration_endpoint?: string;\n};\n\n/**\n * Subset of RFC 9728 protected-resource metadata cached alongside tokens. The\n * `resource` URI is the canonical identifier the authorization server uses to scope\n * tokens — it may differ from the MCP server URL configured in `mcp.json`.\n */\nexport type ResourceMetadataSnapshot = {\n resource: string;\n authorization_servers: string[];\n};\n\n/**\n * Persisted Dynamic Client Registration result (RFC 7591). Present only when the\n * keychain entry was created without a pre-registered `auth` config block. If the\n * user later switches the upstream to pre-registered credentials in config, this\n * cached registration is ignored — config values take precedence in {@link\n * ProxyOAuthProvider.clientInformation}.\n *\n * RFC 7591 §3.2.1 registration-management fields (`registration_access_token`,\n * `registration_client_uri`) are omitted in v1 because we never modify or revoke\n * registrations. Future versions may add them; on storage shape change, bump\n * `KEYCHAIN_BLOB_VERSION` and add migration logic.\n */\nexport type DynamicClientRegistration = {\n client_id: string;\n client_secret?: string;\n};\n\n/**\n * The JSON blob persisted under `service=dynmcp, account=<mcp-name>:<origin>` in the\n * operating system's keychain. Written atomically after a successful token exchange or\n * refresh; on logout the entire entry is deleted.\n *\n * Schema is documented in SPEC.md § \"Upstream OAuth > Keychain Storage\". When the\n * shape changes incompatibly, bump {@link KEYCHAIN_BLOB_VERSION} and add migration\n * logic in {@link KeychainStore}.\n */\nexport type KeychainBlob = {\n version: typeof KEYCHAIN_BLOB_VERSION;\n access_token: string;\n token_type: \"Bearer\";\n expires_at: number;\n refresh_token?: string;\n scope_granted?: string;\n authorization_server: AuthorizationServerSnapshot;\n resource_metadata: ResourceMetadataSnapshot;\n dcr?: DynamicClientRegistration;\n};\n\n/**\n * Versioning sentinel embedded in every blob so we can detect (and eventually migrate\n * or reject) entries written by an older `dynmcp` version. Bump only when the schema\n * changes incompatibly.\n */\nexport const KEYCHAIN_BLOB_VERSION = 1 as const;\n\n/**\n * Pre-registered OAuth client credentials supplied via the config file's optional\n * `auth: { client_id, client_secret?, scope? }` block. When present, {@link\n * ProxyOAuthProvider.clientInformation} returns these instead of the DCR cache and\n * {@link LoginOAuthProvider} skips the DCR step entirely.\n */\nexport type ConfigAuthOverrides = {\n client_id: string;\n client_secret?: string;\n scope?: string;\n};\n","import { randomBytes } from \"node:crypto\";\nimport type {\n OAuthClientInformationFull,\n OAuthClientInformationMixed,\n OAuthClientMetadata,\n OAuthTokens,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type {\n OAuthClientProvider,\n OAuthDiscoveryState,\n} from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport { AuthRequiredError } from \"./errors.js\";\nimport type { KeychainStore } from \"./keychain-store.js\";\nimport type {\n AuthorizationServerSnapshot,\n ConfigAuthOverrides,\n KeychainBlob,\n ResourceMetadataSnapshot,\n} from \"./types.js\";\nimport { KEYCHAIN_BLOB_VERSION } from \"./types.js\";\n\n/**\n * Client identity advertised in the OAuth client metadata document. Sent during DCR\n * (RFC 7591) and used to construct the `client_name` shown on the consent screen of\n * compliant authorization servers.\n */\nconst CLIENT_NAME = \"dynmcp\";\n\n/**\n * Standard OAuth software identifier per RFC 7591 §2. Static across releases so\n * authorization servers that pin clients to a `software_id` can match them.\n */\nconst SOFTWARE_ID = \"dynmcp\";\n\n/**\n * Number of seconds before a cached access token's `expires_at` at which the SDK\n * will be told the token is already expired, prompting a refresh. The MCP SDK\n * triggers refresh when `expires_in <= 0`, so subtracting this slack reserves headroom\n * for clock skew and the round-trip latency of the next request.\n */\nconst REFRESH_SLACK_SECONDS = 30;\n\n/**\n * Shared base implementing the bookkeeping that's identical between runtime use\n * ({@link ProxyOAuthProvider}) and interactive login ({@link LoginOAuthProvider}):\n * keychain reads/writes, blob ↔ {@link OAuthTokens} conversion, and discovery-state\n * snapshotting. Subclasses provide the interaction-mode-specific behaviour.\n */\nabstract class BaseOAuthProvider implements OAuthClientProvider {\n constructor(\n protected readonly mcpName: string,\n protected readonly keychain: KeychainStore,\n protected readonly configAuth: ConfigAuthOverrides | undefined,\n ) {}\n\n abstract get redirectUrl(): string | URL | undefined;\n abstract get clientMetadata(): OAuthClientMetadata;\n abstract redirectToAuthorization(url: URL): Promise<void> | void;\n abstract saveCodeVerifier(verifier: string): Promise<void> | void;\n abstract codeVerifier(): Promise<string> | string;\n\n clientInformation(): OAuthClientInformationMixed | undefined {\n if (this.configAuth !== undefined) {\n const info: OAuthClientInformationMixed = { client_id: this.configAuth.client_id };\n if (this.configAuth.client_secret !== undefined) {\n info.client_secret = this.configAuth.client_secret;\n }\n return info;\n }\n const blob = this.keychain.get();\n if (blob?.dcr === undefined) return undefined;\n const info: OAuthClientInformationMixed = { client_id: blob.dcr.client_id };\n if (blob.dcr.client_secret !== undefined) {\n info.client_secret = blob.dcr.client_secret;\n }\n return info;\n }\n\n tokens(): OAuthTokens | undefined {\n const blob = this.keychain.get();\n if (blob === undefined) return undefined;\n const remaining = Math.max(\n 0,\n blob.expires_at - Math.floor(Date.now() / 1000) - REFRESH_SLACK_SECONDS,\n );\n const tokens: OAuthTokens = {\n access_token: blob.access_token,\n token_type: blob.token_type,\n expires_in: remaining,\n };\n if (blob.refresh_token !== undefined) tokens.refresh_token = blob.refresh_token;\n if (blob.scope_granted !== undefined) tokens.scope = blob.scope_granted;\n return tokens;\n }\n\n abstract saveTokens(tokens: OAuthTokens): Promise<void> | void;\n\n /**\n * Builds the {@link OAuthDiscoveryState} the SDK can use to skip rediscovery,\n * reconstructed from the cached keychain blob. Returns `undefined` when there is\n * no cached blob (e.g. fresh login flow before saveTokens fires).\n */\n protected buildDiscoveryStateFromBlob(\n blob: KeychainBlob | undefined,\n ): OAuthDiscoveryState | undefined {\n if (blob === undefined) return undefined;\n return {\n authorizationServerUrl: blob.authorization_server.issuer,\n authorizationServerMetadata: {\n issuer: blob.authorization_server.issuer,\n authorization_endpoint: blob.authorization_server.authorization_endpoint,\n token_endpoint: blob.authorization_server.token_endpoint,\n ...(blob.authorization_server.registration_endpoint !== undefined\n ? { registration_endpoint: blob.authorization_server.registration_endpoint }\n : {}),\n response_types_supported: [\"code\"],\n },\n resourceMetadata: {\n resource: blob.resource_metadata.resource,\n authorization_servers: blob.resource_metadata.authorization_servers,\n },\n };\n }\n}\n\n/**\n * The {@link OAuthClientProvider} wired into the proxy's HTTP / SSE transports at\n * runtime. Read-mostly: it serves cached tokens, supports silent refresh, and\n * deletes credentials on invalidation. Any path that would require user interaction\n * (initial authorization, code-verifier handling) throws {@link AuthRequiredError}\n * with an actionable message — the proxy never opens a browser.\n *\n * Refreshed tokens are persisted back to the keychain atomically via {@link\n * saveTokens}. The {@link discoveryState} method returns the metadata snapshot\n * captured during the original `dynmcp login`, letting the SDK avoid re-doing RFC\n * 9728 + RFC 8414 discovery on every connect.\n */\nexport class ProxyOAuthProvider extends BaseOAuthProvider {\n get redirectUrl(): undefined {\n // The proxy cannot redirect. If the SDK asks for a redirect URL it means we\n // would need to start an interactive flow we cannot complete — that path\n // routes through `redirectToAuthorization` below which throws.\n return undefined;\n }\n\n get clientMetadata(): OAuthClientMetadata {\n return {\n client_name: CLIENT_NAME,\n software_id: SOFTWARE_ID,\n redirect_uris: [],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method:\n this.configAuth?.client_secret !== undefined ? \"client_secret_basic\" : \"none\",\n ...(this.configAuth?.scope !== undefined ? { scope: this.configAuth.scope } : {}),\n };\n }\n\n saveTokens(tokens: OAuthTokens): void {\n const existing = this.keychain.get();\n if (existing === undefined) {\n // Refresh succeeded against an entry we no longer have? Treat as fatal:\n // re-login is required. This shouldn't happen because the only way we got\n // a valid refresh_token to send was reading an entry that just existed.\n throw new AuthRequiredError(this.mcpName);\n }\n const expiresAt =\n tokens.expires_in !== undefined\n ? Math.floor(Date.now() / 1000) + tokens.expires_in\n : existing.expires_at;\n const updated: KeychainBlob = {\n ...existing,\n access_token: tokens.access_token,\n token_type: (tokens.token_type ?? \"Bearer\") as \"Bearer\",\n expires_at: expiresAt,\n refresh_token: tokens.refresh_token ?? existing.refresh_token,\n ...(tokens.scope !== undefined ? { scope_granted: tokens.scope } : {}),\n };\n this.keychain.set(updated);\n }\n\n redirectToAuthorization(_url: URL): never {\n throw new AuthRequiredError(this.mcpName);\n }\n\n saveCodeVerifier(_verifier: string): never {\n throw new AuthRequiredError(this.mcpName);\n }\n\n codeVerifier(): never {\n throw new AuthRequiredError(this.mcpName);\n }\n\n discoveryState(): OAuthDiscoveryState | undefined {\n return this.buildDiscoveryStateFromBlob(this.keychain.get());\n }\n\n invalidateCredentials(_scope: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): void {\n // For all invalidation scopes, the simplest and safest action is to delete the\n // entire keychain entry and require the user to re-login. Partial invalidation\n // would leave behind stale fields that the SDK might mix with fresh ones.\n this.keychain.delete();\n }\n}\n\n/**\n * Per-flow state assembled during `dynmcp login` and committed to the keychain\n * atomically in {@link LoginOAuthProvider.saveTokens}. Holding partial results in\n * memory until token exchange succeeds means a failed login leaves no trace on disk.\n */\ntype PendingLoginState = {\n dcr?: OAuthClientInformationFull;\n discovery?: OAuthDiscoveryState;\n codeVerifier?: string;\n state?: string;\n};\n\n/**\n * Callback contract for the interactive bits of {@link LoginOAuthProvider} so the\n * login orchestrator can inject a browser-opener and test code can substitute a\n * no-op. Each handler runs once per login flow.\n */\nexport type LoginProviderCallbacks = {\n /**\n * Called when the SDK has constructed the authorization URL. Implementations\n * typically open the URL in the user's browser; the login orchestrator then\n * waits on its callback server.\n */\n onAuthorizationUrl(url: URL): Promise<void> | void;\n};\n\n/**\n * The {@link OAuthClientProvider} used during `dynmcp login`. Fully interactive: it\n * holds an in-memory {@link PendingLoginState} that is only committed to the keychain\n * once {@link saveTokens} fires (i.e. token exchange succeeded). On any earlier\n * failure the in-memory state is discarded — nothing is persisted — matching the\n * spec's \"no keychain write occurs\" failure-path guarantee.\n */\nexport class LoginOAuthProvider extends BaseOAuthProvider {\n private readonly redirectUriString: string;\n private readonly pending: PendingLoginState = {};\n private readonly callbacks: LoginProviderCallbacks;\n\n constructor(opts: {\n mcpName: string;\n keychain: KeychainStore;\n configAuth: ConfigAuthOverrides | undefined;\n redirectUri: string;\n callbacks: LoginProviderCallbacks;\n }) {\n super(opts.mcpName, opts.keychain, opts.configAuth);\n this.redirectUriString = opts.redirectUri;\n this.callbacks = opts.callbacks;\n }\n\n get redirectUrl(): string {\n return this.redirectUriString;\n }\n\n get clientMetadata(): OAuthClientMetadata {\n return {\n client_name: CLIENT_NAME,\n software_id: SOFTWARE_ID,\n redirect_uris: [this.redirectUriString],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method:\n this.configAuth?.client_secret !== undefined ? \"client_secret_basic\" : \"none\",\n ...(this.configAuth?.scope !== undefined ? { scope: this.configAuth.scope } : {}),\n };\n }\n\n state(): string {\n if (this.pending.state !== undefined) return this.pending.state;\n const generated = randomBytes(32).toString(\"base64url\");\n this.pending.state = generated;\n return generated;\n }\n\n /** The state value generated for this flow, for the callback handler to verify. */\n get currentState(): string | undefined {\n return this.pending.state;\n }\n\n override clientInformation(): OAuthClientInformationMixed | undefined {\n // Pending DCR (just registered) wins over config and keychain. Otherwise fall\n // back to base behaviour (config → keychain.dcr).\n if (this.pending.dcr !== undefined) {\n const info: OAuthClientInformationMixed = { client_id: this.pending.dcr.client_id };\n if (this.pending.dcr.client_secret !== undefined) {\n info.client_secret = this.pending.dcr.client_secret;\n }\n return info;\n }\n return super.clientInformation();\n }\n\n saveClientInformation(info: OAuthClientInformationMixed): void {\n // Cast: the SDK only invokes saveClientInformation with the full DCR response,\n // not just a mixed slice. Treat the input as full and stash it pending the\n // atomic write in `saveTokens`.\n this.pending.dcr = info as OAuthClientInformationFull;\n }\n\n override saveTokens(tokens: OAuthTokens): void {\n const discovery =\n this.pending.discovery ?? this.buildDiscoveryStateFromBlob(this.keychain.get());\n if (discovery === undefined) {\n throw new Error(\n `Cannot persist tokens for \"${this.mcpName}\": no discovery state captured during the flow.`,\n );\n }\n if (discovery.authorizationServerMetadata === undefined) {\n throw new Error(\n `Cannot persist tokens for \"${this.mcpName}\": authorization server metadata not available.`,\n );\n }\n if (discovery.resourceMetadata === undefined) {\n throw new Error(\n `Cannot persist tokens for \"${this.mcpName}\": protected resource metadata not available.`,\n );\n }\n\n const expiresAt =\n tokens.expires_in !== undefined\n ? Math.floor(Date.now() / 1000) + tokens.expires_in\n : Math.floor(Date.now() / 1000) + 3600;\n\n const authorizationServer: AuthorizationServerSnapshot = {\n issuer: discovery.authorizationServerMetadata.issuer ?? discovery.authorizationServerUrl,\n authorization_endpoint: discovery.authorizationServerMetadata.authorization_endpoint,\n token_endpoint: discovery.authorizationServerMetadata.token_endpoint,\n ...(discovery.authorizationServerMetadata.registration_endpoint !== undefined\n ? { registration_endpoint: discovery.authorizationServerMetadata.registration_endpoint }\n : {}),\n };\n const resourceMetadata: ResourceMetadataSnapshot = {\n resource: discovery.resourceMetadata.resource,\n authorization_servers: discovery.resourceMetadata.authorization_servers ?? [],\n };\n\n const blob: KeychainBlob = {\n version: KEYCHAIN_BLOB_VERSION,\n access_token: tokens.access_token,\n token_type: (tokens.token_type ?? \"Bearer\") as \"Bearer\",\n expires_at: expiresAt,\n ...(tokens.refresh_token !== undefined ? { refresh_token: tokens.refresh_token } : {}),\n ...(tokens.scope !== undefined ? { scope_granted: tokens.scope } : {}),\n authorization_server: authorizationServer,\n resource_metadata: resourceMetadata,\n ...(this.pending.dcr !== undefined\n ? {\n dcr: {\n client_id: this.pending.dcr.client_id,\n ...(this.pending.dcr.client_secret !== undefined\n ? { client_secret: this.pending.dcr.client_secret }\n : {}),\n },\n }\n : {}),\n };\n\n this.keychain.set(blob);\n }\n\n async redirectToAuthorization(url: URL): Promise<void> {\n await this.callbacks.onAuthorizationUrl(url);\n }\n\n saveCodeVerifier(verifier: string): void {\n this.pending.codeVerifier = verifier;\n }\n\n codeVerifier(): string {\n if (this.pending.codeVerifier === undefined) {\n throw new Error(\"Code verifier requested before it was saved.\");\n }\n return this.pending.codeVerifier;\n }\n\n saveDiscoveryState(state: OAuthDiscoveryState): void {\n this.pending.discovery = state;\n }\n\n /**\n * Force a fresh RFC 9728 + RFC 8414 discovery for every login flow. We intentionally\n * do NOT pre-seed from the keychain on login — if endpoints changed since the last\n * login, we want to pick them up now and persist the new snapshot.\n */\n discoveryState(): undefined {\n return undefined;\n }\n}\n","import process from \"node:process\";\nimport { auth, extractWWWAuthenticateParams } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport { loadConfig, type LoadConfigOptions } from \"../config/index.js\";\nimport type { McpConfig } from \"../config/schema.js\";\nimport { openUrl } from \"./browser.js\";\nimport { CallbackServer } from \"./callback-server.js\";\nimport { KeychainStore } from \"./keychain-store.js\";\nimport { LoginOAuthProvider } from \"./oauth-provider.js\";\nimport type { ConfigAuthOverrides } from \"./types.js\";\n\n/**\n * Default browser-callback timeout. The OAuth dance is \"open browser, click consent,\n * wait for redirect\"; 60s is a generous bound for someone actively at their keyboard\n * and short enough that a closed tab or wrong browser fails fast.\n */\nconst CALLBACK_TIMEOUT_MS = 60_000;\n\nexport interface LoginOptions extends LoadConfigOptions {\n /** Name of the MCP under the config's `mcp.<name>` key. */\n mcpName: string;\n /** Hook for tests to substitute a no-op browser opener. Defaults to {@link openUrl}. */\n openInBrowser?: (url: string) => Promise<void>;\n /** Hook for tests to write status to a buffer rather than stderr. */\n writeStatus?: (message: string) => void;\n}\n\n/**\n * Runs the interactive OAuth authorization-code flow for a single configured\n * upstream MCP and persists the resulting tokens to the OS keychain. Mirrors the\n * step-by-step behaviour specified in SPEC.md § \"`dynmcp login <name>`\".\n *\n * Side-effect free up to the moment the token endpoint returns successfully — any\n * earlier failure leaves the keychain untouched and discards any in-flight DCR\n * registration.\n *\n * @throws Error with a user-actionable message on every documented failure path\n * (wrong transport, unknown name, no 401 challenge, callback timeout, state\n * mismatch, token exchange failure). Callers should surface `error.message` and\n * exit non-zero.\n */\nexport async function login(options: LoginOptions): Promise<void> {\n const config = loadConfig({\n configPath: options.configPath,\n envFilePath: options.envFilePath,\n });\n const entry = resolveOAuthCapableEntry(config, options.mcpName);\n const writeStatus = options.writeStatus ?? defaultStatusWriter;\n const openInBrowser = options.openInBrowser ?? openUrl;\n\n writeStatus(`Probing ${entry.url} for OAuth challenge...\\n`);\n const resourceMetadataUrl = await probeFor401ResourceMetadata(entry.url);\n if (resourceMetadataUrl === undefined) {\n throw new Error(\n `Upstream \"${options.mcpName}\" did not return a 401 challenge with a ` +\n `WWW-Authenticate \\`resource_metadata\\` URL. The server does not appear to require ` +\n `OAuth; no credentials stored.`,\n );\n }\n\n const keychain = new KeychainStore(options.mcpName, entry.url);\n const callbackServer = new CallbackServer();\n await callbackServer.start();\n writeStatus(`Callback server listening on ${callbackServer.redirectUri}\\n`);\n\n try {\n const provider = new LoginOAuthProvider({\n mcpName: options.mcpName,\n keychain,\n configAuth: configAuthFromEntry(entry),\n redirectUri: callbackServer.redirectUri,\n callbacks: {\n onAuthorizationUrl: async url => {\n writeStatus(`Opening browser for authorization: ${url.toString()}\\n`);\n try {\n await openInBrowser(url.toString());\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n writeStatus(\n `Failed to launch browser (${reason}). Open this URL manually:\\n ${url.toString()}\\n`,\n );\n }\n },\n },\n });\n\n const firstResult = await auth(provider, {\n serverUrl: entry.url,\n resourceMetadataUrl,\n ...(entry.auth?.scope !== undefined ? { scope: entry.auth.scope } : {}),\n });\n\n if (firstResult === \"AUTHORIZED\") {\n writeStatus(`Already authorized for \"${options.mcpName}\"; no changes made.\\n`);\n return;\n }\n\n writeStatus(`Waiting for browser callback (timeout ${CALLBACK_TIMEOUT_MS / 1000}s)...\\n`);\n const { code, state: receivedState } = await callbackServer.awaitCallback(CALLBACK_TIMEOUT_MS);\n\n const expectedState = provider.currentState;\n if (expectedState === undefined || receivedState !== expectedState) {\n throw new Error(\n \"OAuth state mismatch on callback. Possible CSRF attempt or stale browser tab; \" +\n \"not exchanging the authorization code.\",\n );\n }\n\n const secondResult = await auth(provider, {\n serverUrl: entry.url,\n authorizationCode: code,\n resourceMetadataUrl,\n ...(entry.auth?.scope !== undefined ? { scope: entry.auth.scope } : {}),\n });\n\n if (secondResult !== \"AUTHORIZED\") {\n throw new Error(`Token exchange did not return AUTHORIZED (got ${secondResult}).`);\n }\n\n writeStatus(`Successfully authenticated \"${options.mcpName}\".\\n`);\n } finally {\n await callbackServer.stop();\n }\n}\n\n/**\n * Validates that the named MCP exists in the config and that it is an HTTP-based\n * transport (stdio is out of scope for OAuth). Returns the typed entry on success.\n */\nfunction resolveOAuthCapableEntry(\n config: McpConfig,\n mcpName: string,\n): Extract<McpConfig[\"mcp\"][string], { transport: \"streamable-http\" } | { transport: \"sse\" }> {\n const entry = config.mcp[mcpName];\n if (entry === undefined) {\n const available = Object.keys(config.mcp).sort().join(\", \");\n throw new Error(`Unknown MCP \"${mcpName}\". Configured MCPs: ${available || \"(none)\"}.`);\n }\n if (entry.transport !== \"streamable-http\" && entry.transport !== \"sse\") {\n throw new Error(\n `MCP \"${mcpName}\" uses the \"${entry.transport}\" transport; OAuth is only supported ` +\n `for streamable-http and sse upstreams.`,\n );\n }\n return entry;\n}\n\nfunction configAuthFromEntry(\n entry: Extract<McpConfig[\"mcp\"][string], { transport: \"streamable-http\" } | { transport: \"sse\" }>,\n): ConfigAuthOverrides | undefined {\n if (entry.auth === undefined) return undefined;\n const overrides: ConfigAuthOverrides = { client_id: entry.auth.client_id };\n if (entry.auth.client_secret !== undefined) overrides.client_secret = entry.auth.client_secret;\n if (entry.auth.scope !== undefined) overrides.scope = entry.auth.scope;\n return overrides;\n}\n\n/**\n * Performs an unauthenticated probe of the upstream URL to extract the RFC 9728\n * `resource_metadata` URL from the resulting `WWW-Authenticate` header. Returns\n * `undefined` if the server responds with anything other than 401, which the caller\n * surfaces as the spec-defined \"this MCP does not require OAuth\" error.\n *\n * The probe uses HTTP GET with no body — most MCP servers will reject it for\n * protocol reasons but still emit the 401 + challenge first, which is all we need.\n * Network errors propagate so the caller's actionable error message includes them.\n */\nasync function probeFor401ResourceMetadata(serverUrl: string): Promise<URL | undefined> {\n let response: Response;\n try {\n response = await fetch(serverUrl, { method: \"GET\", redirect: \"manual\" });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to reach ${serverUrl}: ${reason}`);\n }\n if (response.status !== 401) {\n return undefined;\n }\n const { resourceMetadataUrl } = extractWWWAuthenticateParams(response);\n return resourceMetadataUrl;\n}\n\nfunction defaultStatusWriter(message: string): void {\n process.stderr.write(message);\n}\n","import { z } from \"zod\";\n\nexport const MCP_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;\n\nconst mcpName = z.string().regex(MCP_NAME_PATTERN);\n\nexport const envModeSchema = z\n .enum([\"enable\", \"dotenv\", \"process\", \"disable\"])\n .describe(\n 'Controls environment variable interpolation in config values. \"enable\" (default) merges .env and process.env (.env wins). \"dotenv\" loads .env only. \"process\" uses process.env only. \"disable\" turns interpolation off.',\n );\n\nexport type EnvMode = z.infer<typeof envModeSchema>;\n\n/**\n * Optional per-entry description. When present (and non-whitespace), the MCP becomes\n * a lazy upstream and the proxy enables dynamic discovery. The string is shown to the\n * agent in the `<mcp_servers>` block of `discover_tool`'s description so the agent\n * can decide whether to invoke `load_mcp` for it. The `.refine` runs after env-var\n * interpolation, so values that resolve to whitespace-only are also rejected.\n */\nconst description = z\n .string()\n .min(1, { message: \"description must be a non-empty string\" })\n .refine(value => value.trim().length > 0, {\n message: \"description must not be whitespace-only\",\n })\n .optional();\n\nconst stdioTransport = z\n .object({\n transport: z.literal(\"stdio\"),\n description,\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n })\n .strict();\n\nconst httpUrl = z\n .string()\n .url()\n .refine(u => u.startsWith(\"http://\") || u.startsWith(\"https://\"), {\n message: \"URL must use http:// or https:// scheme\",\n });\n\n/**\n * Optional pre-registered OAuth client credentials for `streamable-http` and `sse`\n * upstreams. When present, the `dynmcp login` flow uses these instead of performing\n * RFC 7591 Dynamic Client Registration. Field values are interpolation targets so\n * secrets can live in `.env` rather than the config file. See SPEC.md § \"Upstream\n * OAuth > Auth Config\".\n */\nconst authConfig = z\n .object({\n client_id: z\n .string()\n .min(1, { message: \"auth.client_id must be a non-empty string\" })\n .refine(value => value.trim().length > 0, {\n message: \"auth.client_id must not be whitespace-only\",\n }),\n client_secret: z.string().min(1).optional(),\n scope: z.string().min(1).optional(),\n })\n .strict()\n .optional();\n\nconst streamableHttpTransport = z\n .object({\n transport: z.literal(\"streamable-http\"),\n description,\n url: httpUrl,\n headers: z.record(z.string(), z.string()).optional(),\n auth: authConfig,\n })\n .strict();\n\nconst sseTransport = z\n .object({\n transport: z.literal(\"sse\"),\n description,\n url: httpUrl,\n headers: z.record(z.string(), z.string()).optional(),\n auth: authConfig,\n })\n .strict();\n\nexport const transportConfigSchema = z.discriminatedUnion(\"transport\", [\n stdioTransport,\n streamableHttpTransport,\n sseTransport,\n]);\n\nexport type TransportConfig = z.infer<typeof transportConfigSchema>;\n\nexport const mcpConfigSchema = z.object({\n env: envModeSchema.optional(),\n mcp: z\n .record(mcpName, transportConfigSchema)\n .refine(obj => Object.keys(obj).length > 0, { message: \"At least one MCP must be configured\" }),\n});\n\nexport type McpConfig = z.infer<typeof mcpConfigSchema>;\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { parse as parseYaml } from \"yaml\";\nimport { loadEnv } from \"./env-sources.js\";\nimport { interpolateConfig } from \"./interpolate.js\";\nimport { type EnvMode, type McpConfig, mcpConfigSchema } from \"./schema.js\";\n\nconst AUTO_DISCOVER_NAMES = [\"mcp.json\", \".mcp.json\"] as const;\nconst DEFAULT_ENV_MODE: EnvMode = \"enable\";\nconst VALID_ENV_MODES: readonly EnvMode[] = [\"enable\", \"dotenv\", \"process\", \"disable\"];\n\nexport interface LoadConfigOptions {\n /** Path to the config file. If omitted, auto-discovers `mcp.json` then `.mcp.json` in cwd. */\n configPath?: string;\n /** Path to a custom `.env` file (from the `--env` / `-e` CLI flag). */\n envFilePath?: string;\n}\n\n/**\n * Resolves the config file path without loading or parsing it.\n *\n * @param explicitPath - If provided, resolves this path directly.\n * @returns The absolute path to the config file.\n * @throws If no config file is found at the explicit path or via auto-discovery.\n */\nexport function resolveConfigPath(explicitPath?: string): string {\n if (explicitPath) {\n const resolved = resolve(explicitPath);\n if (!existsSync(resolved)) {\n throw new Error(`Config file not found: ${resolved}`);\n }\n return resolved;\n }\n\n const cwd = process.cwd();\n for (const name of AUTO_DISCOVER_NAMES) {\n const candidate = resolve(cwd, name);\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n const searched = AUTO_DISCOVER_NAMES.map(n => resolve(cwd, n)).join(\", \");\n throw new Error(`No config file found. Searched: ${searched}`);\n}\n\n/**\n * Loads, parses, interpolates, and validates the dynmcp config file.\n *\n * Flow: resolve path → read file → parse JSON/YAML → read env mode →\n * load env sources → interpolate `${VAR}` references → Zod validate.\n *\n * @param options - Config path and optional custom `.env` file path.\n * @returns The validated config object with all interpolations resolved.\n * @throws On missing file, parse errors, missing env vars, or schema validation failures.\n */\nexport function loadConfig(options: LoadConfigOptions = {}): McpConfig {\n const { configPath, envFilePath } = options;\n\n const resolvedPath = resolveConfigPath(configPath);\n const raw = readFileSync(resolvedPath, \"utf-8\");\n\n let content: unknown;\n try {\n content = isYamlFile(resolvedPath) ? parseYaml(raw) : JSON.parse(raw);\n } catch (parseError) {\n const message = parseError instanceof Error ? parseError.message : String(parseError);\n throw new Error(`Failed to parse config file (${resolvedPath}): ${message}`);\n }\n\n const envMode = readEnvMode(content);\n const loadedEnv = loadEnv({ mode: envMode, envFilePath });\n\n const interpolated = loadedEnv.interpolationEnabled\n ? interpolateConfig(content, loadedEnv.variables)\n : content;\n\n const result = mcpConfigSchema.safeParse(interpolated);\n if (!result.success) {\n const formatted = result.error.issues\n .map(issue => ` - ${issue.path.join(\".\")}: ${issue.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid config file (${resolvedPath}):\\n${formatted}`);\n }\n\n return result.data;\n}\n\n/**\n * Reads the top-level `env` field from raw parsed config content. This runs\n * before Zod validation so we can resolve env vars before validating types.\n *\n * If the field is missing, the default mode is returned. If it is present but\n * not a recognized value, the default is returned so that Zod can surface a\n * specific validation error later.\n */\nfunction readEnvMode(content: unknown): EnvMode {\n if (content === null || typeof content !== \"object\" || Array.isArray(content)) {\n return DEFAULT_ENV_MODE;\n }\n const value = (content as Record<string, unknown>).env;\n if (value === undefined) return DEFAULT_ENV_MODE;\n if (typeof value === \"string\" && (VALID_ENV_MODES as readonly string[]).includes(value)) {\n return value as EnvMode;\n }\n return DEFAULT_ENV_MODE;\n}\n\nfunction isYamlFile(filePath: string): boolean {\n return filePath.endsWith(\".yml\") || filePath.endsWith(\".yaml\");\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport process from \"node:process\";\nimport dotenv from \"dotenv\";\nimport type { EnvMode } from \"./schema.js\";\n\nconst DEFAULT_DOTENV_FILENAME = \".env\";\n\nexport interface LoadEnvOptions {\n /** Env interpolation mode (from config file top-level `env` field). */\n mode: EnvMode;\n /** Custom `.env` path from the `--env` / `-e` CLI flag. When provided, the file must exist. */\n envFilePath?: string;\n /** Override for cwd (testability). Defaults to `process.cwd()`. */\n cwd?: string;\n /** Override for process.env (testability). Defaults to `process.env`. */\n processEnv?: NodeJS.ProcessEnv;\n}\n\nexport interface LoadedEnv {\n /** Merged variable map ready for interpolation. */\n variables: Record<string, string>;\n /** Whether interpolation should run at all. False only when mode is \"disable\". */\n interpolationEnabled: boolean;\n}\n\n/**\n * Resolves the environment variable map used for config interpolation.\n *\n * Precedence rules:\n * - mode \"enable\": load .env + process.env, .env wins for duplicates.\n * - mode \"dotenv\": load .env only; process.env is ignored.\n * - mode \"process\": process.env only; no .env file is loaded.\n * - mode \"disable\": no sources; interpolation is turned off.\n *\n * The `--env` flag is incompatible with \"disable\" and \"process\" modes and is\n * rejected at startup as an incoherent combination.\n *\n * @throws If `--env` is combined with an incompatible mode.\n * @throws If an explicit `--env` path does not exist or cannot be parsed.\n */\nexport function loadEnv(options: LoadEnvOptions): LoadedEnv {\n const { mode, envFilePath, cwd = process.cwd(), processEnv = process.env } = options;\n\n if (envFilePath !== undefined && (mode === \"disable\" || mode === \"process\")) {\n throw new Error(\n `--env flag is incompatible with env mode \"${mode}\". --env requires env mode \"enable\" or \"dotenv\".`,\n );\n }\n\n if (mode === \"disable\") {\n return { variables: {}, interpolationEnabled: false };\n }\n\n const dotenvVars = mode === \"process\" ? {} : readDotenvFile(envFilePath, cwd);\n const processVars = mode === \"dotenv\" ? {} : filterDefined(processEnv);\n\n // For \"enable\" mode, .env wins (later spread overrides earlier).\n // For \"process\" and \"dotenv\" modes only one source is non-empty, so order is moot.\n const variables = { ...processVars, ...dotenvVars };\n\n return { variables, interpolationEnabled: true };\n}\n\nfunction readDotenvFile(envFilePath: string | undefined, cwd: string): Record<string, string> {\n const isExplicit = envFilePath !== undefined;\n const resolvedPath = isExplicit\n ? resolve(envFilePath as string)\n : resolve(cwd, DEFAULT_DOTENV_FILENAME);\n\n if (!existsSync(resolvedPath)) {\n if (isExplicit) {\n throw new Error(`.env file not found: ${resolvedPath}`);\n }\n // Soft-fail: a missing default .env is not an error.\n return {};\n }\n\n let raw: string;\n try {\n raw = readFileSync(resolvedPath, \"utf-8\");\n } catch (readError) {\n const message = readError instanceof Error ? readError.message : String(readError);\n throw new Error(`Failed to read .env file (${resolvedPath}): ${message}`);\n }\n\n try {\n return dotenv.parse(raw);\n } catch (parseError) {\n const message = parseError instanceof Error ? parseError.message : String(parseError);\n throw new Error(`Failed to parse .env file (${resolvedPath}): ${message}`);\n }\n}\n\nfunction filterDefined(env: NodeJS.ProcessEnv): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n","/**\n * Environment variable interpolation for dynmcp config files.\n *\n * Runs after JSON/YAML parsing but before Zod validation, so the validated\n * config contains only fully-resolved string values.\n *\n * Supported syntax (per SPEC.md \"Environment Variable Interpolation\"):\n * - `${VAR}` substitute the value of VAR; missing → error\n * - `${VAR:-default}` substitute VAR, or `default` if VAR is unset or empty\n * - `$${...}` escape — resolves to the literal `${...}`\n *\n * Interpolation applies only to leaf string values reached through the `mcp`\n * subtree. The top-level `$schema` and `env` fields are passed through verbatim.\n */\n\nconst TOP_LEVEL_PASSTHROUGH_KEYS = new Set([\"$schema\", \"env\"]);\n\nexport class MissingEnvVarsError extends Error {\n constructor(public readonly missingVars: readonly string[]) {\n const list = missingVars.join(\", \");\n const plural = missingVars.length === 1 ? \"\" : \"s\";\n super(`Missing required environment variable${plural}: ${list}`);\n this.name = \"MissingEnvVarsError\";\n }\n}\n\n/**\n * Walks a parsed config object and substitutes `${VAR}` references in all leaf\n * string values. Top-level `$schema` and `env` keys are not interpolated.\n *\n * @param config - The parsed (but unvalidated) config object.\n * @param env - The resolved environment variable map (already merged per env mode).\n * @returns A structurally identical config with all string leaves interpolated.\n * @throws {MissingEnvVarsError} If any `${VAR}` reference has no default and no value in env.\n */\nexport function interpolateConfig(config: unknown, env: Record<string, string>): unknown {\n if (config === null || typeof config !== \"object\" || Array.isArray(config)) {\n return config;\n }\n\n const missing: string[] = [];\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(config as Record<string, unknown>)) {\n if (TOP_LEVEL_PASSTHROUGH_KEYS.has(key)) {\n result[key] = value;\n } else {\n result[key] = walkNode(value, env, missing);\n }\n }\n\n if (missing.length > 0) {\n const unique = Array.from(new Set(missing)).sort();\n throw new MissingEnvVarsError(unique);\n }\n\n return result;\n}\n\nfunction walkNode(node: unknown, env: Record<string, string>, missing: string[]): unknown {\n if (typeof node === \"string\") {\n return interpolateString(node, env, missing);\n }\n if (Array.isArray(node)) {\n return node.map(item => walkNode(item, env, missing));\n }\n if (node !== null && typeof node === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node as Record<string, unknown>)) {\n result[key] = walkNode(value, env, missing);\n }\n return result;\n }\n return node;\n}\n\nfunction interpolateString(value: string, env: Record<string, string>, missing: string[]): string {\n let result = \"\";\n let i = 0;\n const len = value.length;\n\n while (i < len) {\n const ch = value[i];\n\n if (ch === \"$\" && value[i + 1] === \"$\" && value[i + 2] === \"{\") {\n // Escape: $${...} -> literal ${...} (strip one leading $)\n const close = value.indexOf(\"}\", i + 3);\n if (close === -1) {\n // Unclosed escape; treat the leading $ as literal and advance one char\n result += ch;\n i += 1;\n continue;\n }\n result += value.substring(i + 1, close + 1);\n i = close + 1;\n continue;\n }\n\n if (ch === \"$\" && value[i + 1] === \"{\") {\n const close = value.indexOf(\"}\", i + 2);\n if (close === -1) {\n // Unclosed expression; emit the rest of the string literally\n result += value.substring(i);\n break;\n }\n const expr = value.substring(i + 2, close);\n const { name, defaultValue } = parseExpr(expr);\n const resolved = env[name];\n const hasValue = resolved !== undefined && resolved !== \"\";\n\n if (hasValue) {\n result += resolved;\n } else if (defaultValue !== undefined) {\n result += defaultValue;\n } else if (resolved !== undefined) {\n // Defined but empty string and no default — treat as the empty string.\n // Per spec: ${VAR} without default fails only when VAR is *undefined*.\n result += \"\";\n } else {\n missing.push(name);\n }\n i = close + 1;\n continue;\n }\n\n result += ch;\n i += 1;\n }\n\n return result;\n}\n\nfunction parseExpr(expr: string): { name: string; defaultValue: string | undefined } {\n const sep = expr.indexOf(\":-\");\n if (sep === -1) {\n return { name: expr, defaultValue: undefined };\n }\n return {\n name: expr.substring(0, sep),\n defaultValue: expr.substring(sep + 2),\n };\n}\n","import { z } from \"zod\";\nimport { mcpConfigSchema } from \"./schema.js\";\n\nexport const MCP_CONFIG_SCHEMA_ID = \"https://dynamicmcp.tools/config.json\";\nexport const MCP_CONFIG_SCHEMA_DRAFT = \"http://json-schema.org/draft-07/schema#\";\n\n/**\n * Generates the JSON Schema for the dynmcp config file from the runtime Zod schema.\n *\n * The schema is targeted at JSON Schema draft-07 for the broadest editor support\n * (VS Code, JetBrains, and the JSON Schema Store all consume draft-07 reliably).\n *\n * @returns A JSON Schema document describing the dynmcp config file format.\n */\nexport function generateMcpConfigJsonSchema(): Record<string, unknown> {\n const generated = z.toJSONSchema(mcpConfigSchema, {\n target: \"draft-7\",\n }) as Record<string, unknown>;\n\n const properties = (generated.properties ?? {}) as Record<string, unknown>;\n const mcpProperty = (properties.mcp ?? {}) as Record<string, unknown>;\n\n return {\n $schema: MCP_CONFIG_SCHEMA_DRAFT,\n $id: MCP_CONFIG_SCHEMA_ID,\n title: \"dynmcp config\",\n description:\n \"Configuration file for dynmcp. Declares the set of upstream MCPs to proxy through dynamic-discovery-mcp.\",\n ...generated,\n properties: {\n ...properties,\n $schema: {\n type: \"string\",\n description: \"URL of the JSON Schema for editor validation.\",\n },\n mcp: {\n ...mcpProperty,\n minProperties: 1,\n description:\n \"Map of upstream MCPs to proxy, keyed by MCP name. Each name becomes the namespace prefix for that MCP's tools.\",\n },\n },\n };\n}\n","import { spawn } from \"node:child_process\";\nimport process from \"node:process\";\n\n/**\n * Spawn the OS's default URL opener for the given URL. Used to launch the user's\n * browser at the OAuth authorization endpoint during `dynmcp login`.\n *\n * The child is fully detached and its stdio is ignored so the parent process can\n * exit (or move on to wait on the callback server) without holding the browser open.\n * The returned promise resolves once the OS opener has been *spawned*, not once the\n * browser actually finishes loading — there is no portable way to know the latter.\n *\n * @throws if the OS opener cannot be spawned (e.g. PATH issues). Callers should fall\n * back to printing the URL on stderr so the user can paste it manually.\n */\nexport async function openUrl(url: string): Promise<void> {\n const { command, args } = openerForPlatform(url);\n\n return new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: \"ignore\",\n detached: true,\n });\n\n child.once(\"error\", reject);\n child.once(\"spawn\", () => {\n child.unref();\n resolve();\n });\n });\n}\n\n/**\n * Picks the correct OS-default URL opener for the current platform.\n *\n * - macOS uses `open <url>`\n * - Windows uses `cmd /c start \"\" <url>` (the empty quoted title is required to\n * prevent `start` from interpreting the URL as the window title)\n * - everything else uses `xdg-open <url>` (Linux, BSDs)\n */\nfunction openerForPlatform(url: string): { command: string; args: string[] } {\n switch (process.platform) {\n case \"darwin\":\n return { command: \"open\", args: [url] };\n case \"win32\":\n return { command: \"cmd\", args: [\"/c\", \"start\", '\"\"', url] };\n default:\n return { command: \"xdg-open\", args: [url] };\n }\n}\n","import { createServer, type Server, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\n/**\n * The query parameters captured from a successful OAuth redirect to our local\n * callback URL. `state` is the raw value from the authorization server — the caller\n * is responsible for validating it against the value generated when constructing the\n * authorization URL. See SPEC.md § \"Upstream OAuth > `dynmcp login`\" step 8.\n */\nexport type CallbackResult = {\n code: string;\n state: string;\n};\n\n/**\n * Thrown by {@link CallbackServer.awaitCallback} when no valid callback arrives\n * before the configured timeout elapses. Surfaces as the actionable\n * \"browser callback timeout\" error path in the spec.\n */\nexport class CallbackTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Timed out after ${timeoutMs}ms waiting for the OAuth callback.`);\n this.name = \"CallbackTimeoutError\";\n }\n}\n\n/**\n * Thrown when the authorization server redirects back with an `error` query\n * parameter instead of `code`. The OAuth 2.0 spec defines the canonical error codes\n * (`access_denied`, `invalid_request`, etc.); we surface whatever the server sent so\n * the user has actionable detail in the terminal.\n */\nexport class CallbackOAuthError extends Error {\n constructor(\n readonly oauthError: string,\n readonly oauthErrorDescription: string | undefined,\n ) {\n super(\n oauthErrorDescription\n ? `OAuth error from authorization server: ${oauthError} — ${oauthErrorDescription}`\n : `OAuth error from authorization server: ${oauthError}`,\n );\n this.name = \"CallbackOAuthError\";\n }\n}\n\nconst SUCCESS_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <title>dynmcp — authorization complete</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; padding: 4rem; max-width: 36rem; margin: 0 auto; color: #222; }\n code { background: #f4f4f4; padding: 0.1rem 0.3rem; border-radius: 3px; }\n </style>\n </head>\n <body>\n <h1>Authorization complete</h1>\n <p>You may close this tab and return to your terminal.</p>\n <p><small>Issued by <code>dynmcp</code>.</small></p>\n </body>\n</html>\n`;\n\nconst ERROR_HTML_PREFIX = `<!DOCTYPE html>\n<html lang=\"en\">\n <head><meta charset=\"utf-8\" /><title>dynmcp — authorization failed</title></head>\n <body style=\"font-family: -apple-system, BlinkMacSystemFont, sans-serif; padding: 4rem; max-width: 36rem; margin: 0 auto;\">\n <h1>Authorization failed</h1>\n <p>`;\nconst ERROR_HTML_SUFFIX = `</p>\n <p>Return to your terminal for details.</p>\n </body>\n</html>\n`;\n\n/**\n * One-shot local HTTP server that captures the OAuth authorization-code callback. The\n * server binds to `127.0.0.1` on an OS-assigned ephemeral port (never `0.0.0.0`) and\n * serves a single path (`/callback`) for a single GET request — every other path /\n * method returns `404` / `405`. See SPEC.md § \"Upstream OAuth > Local Callback\n * Server\" for the full behavior contract.\n *\n * Usage shape:\n *\n * ```\n * const server = new CallbackServer();\n * await server.start();\n * // ... build redirectUri from server.port, kick off auth flow ...\n * const { code, state } = await server.awaitCallback(60_000);\n * await server.stop();\n * ```\n *\n * The server stops itself the instant a valid callback is received, but always call\n * {@link stop} in a `finally` to ensure cleanup on error paths.\n */\nexport class CallbackServer {\n private server: Server | null = null;\n private boundPort: number | null = null;\n private pending: {\n resolve: (result: CallbackResult) => void;\n reject: (error: Error) => void;\n timer: NodeJS.Timeout;\n } | null = null;\n\n /** The redirect path served. Must match the redirect URI registered with the OAuth client. */\n static readonly CALLBACK_PATH = \"/callback\";\n\n /** Begins listening on `127.0.0.1` at an OS-assigned port. */\n async start(): Promise<void> {\n if (this.server !== null) {\n throw new Error(\"CallbackServer is already started.\");\n }\n\n const server = createServer((req, res) => this.handleRequest(req, res));\n\n await new Promise<void>((resolve, reject) => {\n const onError = (err: Error): void => {\n server.removeListener(\"listening\", onListening);\n reject(err);\n };\n const onListening = (): void => {\n server.removeListener(\"error\", onError);\n resolve();\n };\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen({ port: 0, host: \"127.0.0.1\" });\n });\n\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n server.close();\n throw new Error(\"Failed to determine bound port for callback server.\");\n }\n this.boundPort = (address as AddressInfo).port;\n this.server = server;\n }\n\n /** The port the OS assigned. Available after {@link start} resolves. */\n get port(): number {\n if (this.boundPort === null) {\n throw new Error(\"CallbackServer is not started.\");\n }\n return this.boundPort;\n }\n\n /** The full redirect URI to register with the authorization server. */\n get redirectUri(): string {\n return `http://127.0.0.1:${this.port}${CallbackServer.CALLBACK_PATH}`;\n }\n\n /**\n * Resolves with the captured `code` and `state` once a valid callback is received,\n * or rejects with {@link CallbackTimeoutError} / {@link CallbackOAuthError} on the\n * documented failure paths. Only one callback is accepted; subsequent requests to\n * `/callback` after the first valid hit return `400`.\n */\n awaitCallback(timeoutMs: number): Promise<CallbackResult> {\n if (this.server === null) {\n return Promise.reject(new Error(\"CallbackServer is not started.\"));\n }\n if (this.pending !== null) {\n return Promise.reject(new Error(\"awaitCallback already in progress.\"));\n }\n return new Promise<CallbackResult>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending = null;\n reject(new CallbackTimeoutError(timeoutMs));\n }, timeoutMs);\n this.pending = { resolve, reject, timer };\n });\n }\n\n /** Closes the listening socket. Safe to call multiple times. */\n async stop(): Promise<void> {\n if (this.pending !== null) {\n clearTimeout(this.pending.timer);\n this.pending = null;\n }\n if (this.server === null) return;\n await new Promise<void>(resolve => {\n this.server!.close(() => resolve());\n });\n this.server = null;\n this.boundPort = null;\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n if (req.method !== \"GET\") {\n res.writeHead(405, { \"content-type\": \"text/plain\", allow: \"GET\" });\n res.end(\"Method Not Allowed\");\n return;\n }\n\n const url = new URL(req.url ?? \"/\", `http://127.0.0.1:${this.boundPort ?? 0}`);\n if (url.pathname !== CallbackServer.CALLBACK_PATH) {\n res.writeHead(404, { \"content-type\": \"text/plain\" });\n res.end(\"Not Found\");\n return;\n }\n\n if (this.pending === null) {\n // Late or duplicate request after a successful capture / timeout.\n res.writeHead(400, { \"content-type\": \"text/plain\" });\n res.end(\"No callback expected.\");\n return;\n }\n\n const oauthError = url.searchParams.get(\"error\");\n if (oauthError !== null) {\n const errorDescription = url.searchParams.get(\"error_description\") ?? undefined;\n this.respondError(res, oauthError, errorDescription);\n const { reject, timer } = this.pending;\n clearTimeout(timer);\n this.pending = null;\n reject(new CallbackOAuthError(oauthError, errorDescription));\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n if (code === null || state === null) {\n this.respondError(res, \"invalid_callback\", \"Missing code or state parameter.\");\n const { reject, timer } = this.pending;\n clearTimeout(timer);\n this.pending = null;\n reject(new Error(\"Callback missing code or state parameter.\"));\n return;\n }\n\n res.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n res.end(SUCCESS_HTML);\n const { resolve, timer } = this.pending;\n clearTimeout(timer);\n this.pending = null;\n resolve({ code, state });\n }\n\n private respondError(res: ServerResponse, errorCode: string, description?: string): void {\n res.writeHead(400, { \"content-type\": \"text/html; charset=utf-8\" });\n res.end(\n ERROR_HTML_PREFIX +\n escapeHtml(description ?? `OAuth error: ${errorCode}`) +\n ERROR_HTML_SUFFIX,\n );\n }\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n","import process from \"node:process\";\nimport { loadConfig, type LoadConfigOptions } from \"../config/index.js\";\nimport type { McpConfig } from \"../config/schema.js\";\nimport { KeychainStore } from \"./keychain-store.js\";\n\nexport interface LogoutOptions extends LoadConfigOptions {\n /** Name of the MCP under the config's `mcp.<name>` key. */\n mcpName: string;\n /** Hook for tests to write status to a buffer rather than stderr. */\n writeStatus?: (message: string) => void;\n}\n\n/**\n * Removes the keychain entry for a single configured upstream MCP. Idempotent — a\n * missing entry is treated as success. No network calls; the upstream is not notified.\n * Token revocation is intentionally out of scope (see SPEC.md § Non-Goals).\n *\n * @throws Error with a user-actionable message if the MCP name is unknown or the\n * configured transport is not OAuth-capable.\n */\nexport async function logout(options: LogoutOptions): Promise<void> {\n const config = loadConfig({\n configPath: options.configPath,\n envFilePath: options.envFilePath,\n });\n const entry = resolveOAuthCapableEntry(config, options.mcpName);\n const writeStatus = options.writeStatus ?? defaultStatusWriter;\n\n const keychain = new KeychainStore(options.mcpName, entry.url);\n const removed = keychain.delete();\n if (removed) {\n writeStatus(`Removed keychain credentials for \"${options.mcpName}\".\\n`);\n } else {\n writeStatus(\n `No keychain credentials were stored for \"${options.mcpName}\"; nothing to remove.\\n`,\n );\n }\n}\n\nfunction resolveOAuthCapableEntry(\n config: McpConfig,\n mcpName: string,\n): Extract<McpConfig[\"mcp\"][string], { transport: \"streamable-http\" } | { transport: \"sse\" }> {\n const entry = config.mcp[mcpName];\n if (entry === undefined) {\n const available = Object.keys(config.mcp).sort().join(\", \");\n throw new Error(`Unknown MCP \"${mcpName}\". Configured MCPs: ${available || \"(none)\"}.`);\n }\n if (entry.transport !== \"streamable-http\" && entry.transport !== \"sse\") {\n throw new Error(\n `MCP \"${mcpName}\" uses the \"${entry.transport}\" transport; OAuth is only supported ` +\n `for streamable-http and sse upstreams.`,\n );\n }\n return entry;\n}\n\nfunction defaultStatusWriter(message: string): void {\n process.stderr.write(message);\n}\n","import process from \"node:process\";\nimport { KeychainStore } from \"../auth/index.js\";\nimport { loadConfig, type LoadConfigOptions } from \"../config/index.js\";\nimport type { McpConfig } from \"../config/schema.js\";\nimport { humanizeDuration, renderTable, truncate } from \"./format.js\";\n\nconst ENDPOINT_MAX_WIDTH = 48;\n\n/**\n * Per-MCP summary as it appears in `dynmcp ls` output. The JSON shape mirrors this\n * structure closely; the text-table rendering picks a subset of fields.\n */\nexport type ListEntry = {\n name: string;\n transport: \"stdio\" | \"streamable-http\" | \"sse\";\n mode: \"eager\" | \"lazy\";\n endpoint: string;\n description?: string;\n auth: AuthStatus;\n};\n\nexport type AuthStatus =\n | { kind: \"n/a\" }\n | { kind: \"header\" }\n | {\n kind: \"oauth\";\n status: \"logged_in\" | \"not_logged_in\";\n expiresInSeconds?: number;\n expiresAt?: number;\n alsoHeader?: boolean;\n };\n\nexport interface ListOptions extends LoadConfigOptions {\n /** Emit JSON instead of the aligned text table. */\n json?: boolean;\n /** Override the output writer (for tests). Defaults to `process.stdout.write`. */\n write?: (chunk: string) => void;\n /** Override the current time (Unix seconds) used to compute expires_in. Defaults to `Date.now() / 1000`. */\n now?: () => number;\n}\n\n/**\n * Implementation of `dynmcp ls`. Loads the config, derives a {@link ListEntry} per\n * configured upstream (querying the keychain for OAuth entries), and writes the\n * result as either an aligned text table or a JSON array.\n *\n * Pure config + keychain reads — no upstream connections are made.\n */\nexport async function list(options: ListOptions = {}): Promise<void> {\n const config = loadConfig({\n configPath: options.configPath,\n envFilePath: options.envFilePath,\n });\n const write = options.write ?? ((chunk: string) => void process.stdout.write(chunk));\n const now = options.now ?? (() => Math.floor(Date.now() / 1000));\n\n const entries = buildEntries(config, now);\n\n if (options.json === true) {\n write(`${JSON.stringify(entries, null, 2)}\\n`);\n return;\n }\n\n if (entries.length === 0) {\n write(\"No upstream MCPs configured.\\n\");\n return;\n }\n\n const headers = [\"NAME\", \"TRANSPORT\", \"MODE\", \"ENDPOINT\", \"AUTH\"] as const;\n const rows = entries.map(entry => [\n entry.name,\n entry.transport,\n entry.mode,\n truncate(entry.endpoint, ENDPOINT_MAX_WIDTH),\n formatAuthStatus(entry.auth),\n ]);\n write(`${renderTable(headers, rows)}\\n`);\n}\n\nfunction buildEntries(config: McpConfig, now: () => number): ListEntry[] {\n return Object.entries(config.mcp).map(([name, entry]) => {\n const mode: ListEntry[\"mode\"] = entry.description !== undefined ? \"lazy\" : \"eager\";\n\n if (entry.transport === \"stdio\") {\n const command = entry.command;\n const args = (entry.args ?? []).join(\" \");\n const endpoint = args.length > 0 ? `${command} ${args}` : command;\n const built: ListEntry = {\n name,\n transport: \"stdio\",\n mode,\n endpoint,\n auth: { kind: \"n/a\" },\n };\n if (entry.description !== undefined) built.description = entry.description;\n return built;\n }\n\n // streamable-http or sse\n const hasAuthHeader = hasBearerAuthHeader(entry.headers);\n const keychain = new KeychainStore(name, entry.url);\n const blob = keychain.get();\n\n let auth: AuthStatus;\n if (blob !== undefined) {\n const expiresInSeconds = blob.expires_at - now();\n auth = {\n kind: \"oauth\",\n status: \"logged_in\",\n expiresInSeconds,\n expiresAt: blob.expires_at,\n };\n if (hasAuthHeader) (auth as { alsoHeader?: boolean }).alsoHeader = true;\n } else if (hasAuthHeader) {\n auth = { kind: \"header\" };\n } else {\n auth = { kind: \"oauth\", status: \"not_logged_in\" };\n }\n\n const built: ListEntry = {\n name,\n transport: entry.transport,\n mode,\n endpoint: entry.url,\n auth,\n };\n if (entry.description !== undefined) built.description = entry.description;\n return built;\n });\n}\n\nfunction hasBearerAuthHeader(headers: Record<string, string> | undefined): boolean {\n if (headers === undefined) return false;\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === \"authorization\") return true;\n }\n return false;\n}\n\nfunction formatAuthStatus(auth: AuthStatus): string {\n switch (auth.kind) {\n case \"n/a\":\n return \"n/a\";\n case \"header\":\n return \"header\";\n case \"oauth\": {\n if (auth.status === \"not_logged_in\") return \"oauth: not logged in\";\n const duration = humanizeDuration(auth.expiresInSeconds ?? 0);\n const base = `oauth: logged in (expires in ${duration})`;\n return auth.alsoHeader === true ? `${base} (header also set)` : base;\n }\n }\n}\n","/**\n * Renders a simple aligned text table — column widths are auto-derived from the\n * widest cell in each column (headers included). Cells are padded right with spaces\n * and joined with a two-space gap. The last column is not padded to avoid trailing\n * whitespace on each row.\n *\n * Cells are taken verbatim; callers should truncate long strings via {@link truncate}\n * before passing them in if they want bounded column widths.\n */\nexport function renderTable(\n headers: readonly string[],\n rows: readonly (readonly string[])[],\n): string {\n const allRows: readonly (readonly string[])[] = [headers, ...rows];\n const widths = headers.map((_, colIdx) =>\n Math.max(...allRows.map(row => (row[colIdx] ?? \"\").length)),\n );\n\n return allRows\n .map(row =>\n row\n .map((cell, i) => {\n if (i === headers.length - 1) return cell;\n return cell.padEnd(widths[i] ?? 0);\n })\n .join(\" \")\n .trimEnd(),\n )\n .join(\"\\n\");\n}\n\n/**\n * Truncates `value` to at most `max` characters, appending `...` when truncation\n * actually happens. The ellipsis counts toward `max`, so a `max` of 10 leaves at\n * most 7 visible characters of the original.\n *\n * For `max <= 3`, the string is hard-clipped without an ellipsis — there's not\n * enough room to convey both information and the \"truncated\" hint.\n */\nexport function truncate(value: string, max: number): string {\n if (value.length <= max) return value;\n if (max <= 3) return value.slice(0, max);\n return `${value.slice(0, max - 3)}...`;\n}\n\n/**\n * Humanizes a duration in seconds into a short, scannable label suitable for table\n * cells and log lines. Examples: `\"42s\"`, `\"5m\"`, `\"2h 30m\"`, `\"3d 4h\"`, `\"expired\"`.\n *\n * A negative value is rendered as `\"expired\"` rather than a negative number — the\n * caller wants to communicate \"no longer valid\", not an arithmetic curiosity.\n */\nexport function humanizeDuration(seconds: number): string {\n if (seconds < 0) return \"expired\";\n if (seconds < 60) return `${Math.floor(seconds)}s`;\n\n const totalMinutes = Math.floor(seconds / 60);\n if (totalMinutes < 60) return `${totalMinutes}m`;\n\n const totalHours = Math.floor(totalMinutes / 60);\n const remainingMinutes = totalMinutes % 60;\n if (totalHours < 24) {\n return remainingMinutes > 0 ? `${totalHours}h ${remainingMinutes}m` : `${totalHours}h`;\n }\n\n const totalDays = Math.floor(totalHours / 24);\n const remainingHours = totalHours % 24;\n return remainingHours > 0 ? `${totalDays}d ${remainingHours}h` : `${totalDays}d`;\n}\n","import process from \"node:process\";\nimport type { Prompt, Resource, ResourceTemplate } from \"@modelcontextprotocol/sdk/types.js\";\nimport { KeychainStore, isAuthRequiredError } from \"../auth/index.js\";\nimport { loadConfig, type LoadConfigOptions } from \"../config/index.js\";\nimport type { McpConfig } from \"../config/schema.js\";\nimport { createTransport } from \"../proxy/transport-factory.js\";\nimport { UpstreamClient, type UpstreamTool } from \"../proxy/upstream-client.js\";\nimport { humanizeDuration, truncate } from \"./format.js\";\n\nconst DESCRIPTION_MAX_LENGTH = 100;\nconst DEFAULT_TIMEOUT_MS = 15_000;\n\ntype StepStatus = \"ok\" | \"fail\";\n\ntype Step = {\n label: string;\n status: StepStatus;\n error?: string;\n};\n\ntype AuthSummary =\n | { kind: \"n/a\" }\n | { kind: \"header\" }\n | {\n kind: \"oauth\";\n status: \"valid\" | \"missing\";\n expiresInSeconds?: number;\n };\n\n/**\n * Per-MCP test result. The JSON output shape mirrors this directly.\n */\nexport type TestResult = {\n name: string;\n result: \"PASS\" | \"FAIL\";\n transport: \"stdio\" | \"streamable-http\" | \"sse\";\n endpoint: string;\n auth: AuthSummary;\n capabilities?: Record<string, unknown>;\n tools?: Array<{ name: string; description: string }>;\n resources?: Array<{ uri: string; name: string; description?: string }>;\n resource_templates?: Array<{ uriTemplate: string; name: string; description?: string }>;\n prompts?: Array<{ name: string; description?: string }>;\n steps: Step[];\n fail_reason?: string;\n};\n\nexport interface TestOptions extends LoadConfigOptions {\n /** Single-MCP mode if provided; otherwise all-MCP mode. */\n mcpName?: string;\n /** Emit JSON instead of the formatted text output. */\n json?: boolean;\n /** Per-MCP timeout (covers transport open + handshake + all catalog queries). */\n timeoutMs?: number;\n /** Override the output writer (for tests). Defaults to `process.stdout.write`. */\n write?: (chunk: string) => void;\n /** Override the current time (Unix seconds), used to compute token expiry display. */\n now?: () => number;\n}\n\n/**\n * Implementation of `dynmcp test [name]`. When `mcpName` is provided, tests one\n * upstream and prints its full discovered surface; otherwise sequentially tests all\n * configured upstreams and prints a per-MCP summary line.\n *\n * Returns the exit code the CLI should propagate: `0` if all probed MCPs passed,\n * `1` otherwise.\n */\nexport async function test(options: TestOptions = {}): Promise<0 | 1> {\n const config = loadConfig({\n configPath: options.configPath,\n envFilePath: options.envFilePath,\n });\n const write = options.write ?? ((chunk: string) => void process.stdout.write(chunk));\n const now = options.now ?? (() => Math.floor(Date.now() / 1000));\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n if (options.mcpName !== undefined) {\n return runSingle(config, options.mcpName, {\n write,\n now,\n timeoutMs,\n json: options.json === true,\n });\n }\n return runAll(config, { write, now, timeoutMs, json: options.json === true });\n}\n\ntype RunOptions = {\n write: (chunk: string) => void;\n now: () => number;\n timeoutMs: number;\n json: boolean;\n};\n\nasync function runSingle(config: McpConfig, mcpName: string, options: RunOptions): Promise<0 | 1> {\n const entry = config.mcp[mcpName];\n if (entry === undefined) {\n const available = Object.keys(config.mcp).sort().join(\", \");\n throw new Error(`Unknown MCP \"${mcpName}\". Configured MCPs: ${available || \"(none)\"}.`);\n }\n\n if (!options.json) {\n options.write(`Testing \"${mcpName}\" (${entry.transport}, ${endpointForEntry(entry)})\\n`);\n }\n const result = await probeOne(mcpName, entry, options.timeoutMs, options.now);\n\n if (options.json) {\n options.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n for (const step of result.steps) {\n options.write(` [${step.status}] ${step.label}\\n`);\n if (step.error !== undefined) {\n options.write(` -> ${step.error}\\n`);\n }\n }\n renderDiscoveredSurface(options.write, result);\n options.write(`Result: ${result.result}\\n`);\n }\n\n return result.result === \"PASS\" ? 0 : 1;\n}\n\nasync function runAll(config: McpConfig, options: RunOptions): Promise<0 | 1> {\n const names = Object.keys(config.mcp);\n const total = names.length;\n if (!options.json) {\n options.write(`Testing all configured upstreams (${total})...\\n\\n`);\n }\n\n const results: TestResult[] = [];\n for (let index = 0; index < names.length; index += 1) {\n const name = names[index]!;\n const entry = config.mcp[name]!;\n if (!options.json) {\n options.write(`[${index + 1}/${total}] ${name} (${entry.transport}) ... `);\n }\n const result = await probeOne(name, entry, options.timeoutMs, options.now);\n results.push(result);\n if (!options.json) {\n if (result.result === \"PASS\") {\n const counts = `${result.tools?.length ?? 0} tools, ${\n (result.resources?.length ?? 0) + (result.resource_templates?.length ?? 0)\n } resources, ${result.prompts?.length ?? 0} prompts`;\n options.write(`PASS (${counts})\\n`);\n } else {\n options.write(`FAIL (${result.fail_reason ?? \"unknown\"})\\n`);\n }\n }\n }\n\n const passed = results.filter(r => r.result === \"PASS\").length;\n const failed = results.length - passed;\n\n if (options.json) {\n const payload = { summary: { passed, failed }, results };\n options.write(`${JSON.stringify(payload, null, 2)}\\n`);\n } else {\n options.write(`\\nSummary: ${passed} passed, ${failed} failed\\n`);\n }\n\n return failed === 0 ? 0 : 1;\n}\n\n/**\n * Runs the per-MCP probe pipeline: gathers auth status, opens transport, completes\n * `initialize`, fetches the advertised catalogs, and disconnects. Each milestone is\n * recorded as a {@link Step}. Returns a fully-populated {@link TestResult} regardless\n * of pass/fail — failures attach a `fail_reason` and the last attempted step records\n * the underlying error.\n *\n * A timeout wraps the entire pipeline; if it fires, the partial client is disconnected\n * and the result is marked FAIL with a timeout message.\n */\nasync function probeOne(\n mcpName: string,\n entry: McpConfig[\"mcp\"][string],\n timeoutMs: number,\n now: () => number,\n): Promise<TestResult> {\n const result: TestResult = {\n name: mcpName,\n result: \"PASS\",\n transport: entry.transport,\n endpoint: endpointForEntry(entry),\n auth: deriveAuthSummary(mcpName, entry, now),\n steps: [],\n };\n\n // Surface the auth status as the first step (informational; never fails).\n if (entry.transport !== \"stdio\") {\n result.steps.push({ label: authStepLabel(result.auth), status: \"ok\" });\n }\n\n // Holder pattern: TypeScript's flow analysis cannot track assignments made inside\n // the async closure, so a plain `let client: UpstreamClient | null` ends up\n // narrowed to `null` in the `finally` block. A holder object sidesteps that —\n // property access never gets narrowed to `never`.\n const clientHolder: { value: UpstreamClient | null } = { value: null };\n let timeoutHandle: NodeJS.Timeout | undefined;\n\n const run = (async () => {\n const transport = createTransport(mcpName, entry);\n const client = new UpstreamClient({\n name: mcpName,\n transport,\n onTransportError: () => {\n // Swallow during diagnostic — the connect/initialize promise will reject with detail.\n },\n });\n clientHolder.value = client;\n await client.connect();\n result.steps.push({ label: \"Connected and initialized\", status: \"ok\" });\n\n const caps = client.getCapabilities();\n result.capabilities = caps as Record<string, unknown> | undefined;\n result.steps.push({\n label: `Capabilities: ${describeCapabilities(caps)}`,\n status: \"ok\",\n });\n\n const tools = await client.listTools();\n result.tools = tools.map((tool: UpstreamTool) => ({\n name: tool.name,\n description: tool.description,\n }));\n result.steps.push({\n label: `tools/list returned ${tools.length} tool${tools.length === 1 ? \"\" : \"s\"}`,\n status: \"ok\",\n });\n\n let resources: Resource[] = [];\n let templates: ResourceTemplate[] = [];\n if (caps?.resources !== undefined) {\n try {\n resources = await client.listResources();\n templates = await client.listResourceTemplates();\n result.resources = resources.map(r => {\n const out: { uri: string; name: string; description?: string } = {\n uri: r.uri,\n name: r.name,\n };\n if (r.description !== undefined) out.description = r.description;\n return out;\n });\n result.resource_templates = templates.map(t => {\n const out: { uriTemplate: string; name: string; description?: string } = {\n uriTemplate: t.uriTemplate,\n name: t.name,\n };\n if (t.description !== undefined) out.description = t.description;\n return out;\n });\n result.steps.push({\n label: `resources/list returned ${resources.length} resource${resources.length === 1 ? \"\" : \"s\"}, ${templates.length} template${templates.length === 1 ? \"\" : \"s\"}`,\n status: \"ok\",\n });\n } catch (error) {\n result.steps.push({\n label: \"resources/list\",\n status: \"fail\",\n error: errorMessage(error),\n });\n // Continue — resources failure doesn't block prompts.\n }\n }\n\n let prompts: Prompt[] = [];\n if (caps?.prompts !== undefined) {\n try {\n prompts = await client.listPrompts();\n result.prompts = prompts.map(p => {\n const out: { name: string; description?: string } = { name: p.name };\n if (p.description !== undefined) out.description = p.description;\n return out;\n });\n result.steps.push({\n label: `prompts/list returned ${prompts.length} prompt${prompts.length === 1 ? \"\" : \"s\"}`,\n status: \"ok\",\n });\n } catch (error) {\n result.steps.push({\n label: \"prompts/list\",\n status: \"fail\",\n error: errorMessage(error),\n });\n }\n }\n })();\n\n const timeout = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n reject(new TestTimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n await Promise.race([run, timeout]);\n } catch (error) {\n result.result = \"FAIL\";\n result.fail_reason = failReason(error, mcpName);\n result.steps.push({\n label: `aborted: ${result.fail_reason}`,\n status: \"fail\",\n error: errorMessage(error),\n });\n } finally {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);\n const connected = clientHolder.value;\n if (connected !== null) {\n try {\n await connected.disconnect();\n } catch {\n // Best-effort cleanup — disconnect failures during a diagnostic aren't worth surfacing.\n }\n }\n }\n\n // Any per-step failure beyond the first informational step counts as overall FAIL.\n if (result.result === \"PASS\" && result.steps.some(s => s.status === \"fail\")) {\n result.result = \"FAIL\";\n const failed = result.steps.find(s => s.status === \"fail\");\n result.fail_reason = failed?.error ?? failed?.label ?? \"unknown\";\n }\n\n return result;\n}\n\nclass TestTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Test timed out after ${timeoutMs}ms`);\n this.name = \"TestTimeoutError\";\n }\n}\n\nfunction endpointForEntry(entry: McpConfig[\"mcp\"][string]): string {\n if (entry.transport === \"stdio\") {\n const args = (entry.args ?? []).join(\" \");\n return args.length > 0 ? `${entry.command} ${args}` : entry.command;\n }\n return entry.url;\n}\n\nfunction deriveAuthSummary(\n mcpName: string,\n entry: McpConfig[\"mcp\"][string],\n now: () => number,\n): AuthSummary {\n if (entry.transport === \"stdio\") return { kind: \"n/a\" };\n\n const keychain = new KeychainStore(mcpName, entry.url);\n const blob = keychain.get();\n if (blob !== undefined) {\n return {\n kind: \"oauth\",\n status: \"valid\",\n expiresInSeconds: blob.expires_at - now(),\n };\n }\n const hasHeader =\n entry.headers !== undefined &&\n Object.keys(entry.headers).some(k => k.toLowerCase() === \"authorization\");\n if (hasHeader) return { kind: \"header\" };\n return { kind: \"oauth\", status: \"missing\" };\n}\n\nfunction authStepLabel(auth: AuthSummary): string {\n switch (auth.kind) {\n case \"n/a\":\n return \"(no auth applicable)\";\n case \"header\":\n return \"Static Authorization header present\";\n case \"oauth\":\n if (auth.status === \"missing\") return \"No cached OAuth token\";\n return `OAuth token present (expires in ${humanizeDuration(auth.expiresInSeconds ?? 0)})`;\n }\n}\n\nfunction describeCapabilities(caps: Record<string, unknown> | undefined): string {\n if (caps === undefined) return \"(none advertised)\";\n const parts: string[] = [];\n for (const [name, value] of Object.entries(caps)) {\n if (value === undefined || value === null) continue;\n if (typeof value === \"object\" && Object.keys(value).length > 0) {\n const flags = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v === true)\n .map(([k]) => k)\n .join(\",\");\n parts.push(flags.length > 0 ? `${name}(${flags})` : name);\n } else {\n parts.push(name);\n }\n }\n return parts.length > 0 ? parts.join(\", \") : \"(none advertised)\";\n}\n\nfunction failReason(error: unknown, mcpName: string): string {\n if (isAuthRequiredError(error)) {\n return `auth required: run \\`dynmcp login ${mcpName}\\``;\n }\n if (error instanceof TestTimeoutError) return error.message;\n if (error instanceof Error) return error.message.split(\"\\n\")[0] ?? \"unknown error\";\n return String(error);\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\nfunction renderDiscoveredSurface(write: (chunk: string) => void, result: TestResult): void {\n if (result.result !== \"PASS\") return;\n\n const sections: Array<[string, (() => void) | undefined]> = [\n [\n `Tools (${result.tools?.length ?? 0})`,\n result.tools && result.tools.length > 0\n ? () => {\n const sorted = [...(result.tools ?? [])].sort((a, b) => a.name.localeCompare(b.name));\n for (const tool of sorted) {\n write(` - ${tool.name}: ${truncate(tool.description, DESCRIPTION_MAX_LENGTH)}\\n`);\n }\n }\n : undefined,\n ],\n [\n `Resources (${result.resources?.length ?? 0})`,\n result.resources && result.resources.length > 0\n ? () => {\n const sorted = [...(result.resources ?? [])].sort((a, b) => a.uri.localeCompare(b.uri));\n for (const r of sorted) {\n const tail = r.description ?? r.name;\n write(` - ${r.uri}: ${truncate(tail, DESCRIPTION_MAX_LENGTH)}\\n`);\n }\n }\n : undefined,\n ],\n [\n `Resource templates (${result.resource_templates?.length ?? 0})`,\n result.resource_templates && result.resource_templates.length > 0\n ? () => {\n const sorted = [...(result.resource_templates ?? [])].sort((a, b) =>\n a.uriTemplate.localeCompare(b.uriTemplate),\n );\n for (const t of sorted) {\n const tail = t.description ?? t.name;\n write(` - ${t.uriTemplate}: ${truncate(tail, DESCRIPTION_MAX_LENGTH)}\\n`);\n }\n }\n : undefined,\n ],\n [\n `Prompts (${result.prompts?.length ?? 0})`,\n result.prompts && result.prompts.length > 0\n ? () => {\n const sorted = [...(result.prompts ?? [])].sort((a, b) => a.name.localeCompare(b.name));\n for (const p of sorted) {\n const tail = p.description ?? \"\";\n write(\n ` - ${p.name}${tail.length > 0 ? `: ${truncate(tail, DESCRIPTION_MAX_LENGTH)}` : \"\"}\\n`,\n );\n }\n }\n : undefined,\n ],\n ];\n\n for (const [header, render] of sections) {\n if (render === undefined) continue;\n write(`\\n${header}:\\n`);\n render();\n }\n}\n","import { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { KeychainStore, ProxyOAuthProvider, type ConfigAuthOverrides } from \"../auth/index.js\";\n\ninterface StdioTransportConfig {\n transport: \"stdio\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n // Tolerated but unused by the factory. Present so a Zod-validated config entry can be\n // forwarded here without an intermediate destructure; the field is consumed by the\n // orchestrator's lazy-loading logic, not by transport construction.\n description?: string;\n}\n\ninterface StreamableHttpTransportConfig {\n transport: \"streamable-http\";\n url: string;\n headers?: Record<string, string>;\n description?: string;\n /**\n * Optional pre-registered OAuth client credentials. When omitted, the proxy uses\n * Dynamic Client Registration during `dynmcp login` instead. Either way, the\n * proxy's runtime auth provider is constructed automatically — config values for\n * this field flow through to {@link ProxyOAuthProvider}, the runtime side of the\n * auth machinery, where they take precedence over cached DCR results.\n */\n auth?: ConfigAuthOverrides;\n}\n\ninterface SseTransportConfig {\n transport: \"sse\";\n url: string;\n headers?: Record<string, string>;\n description?: string;\n auth?: ConfigAuthOverrides;\n}\n\nexport type McpTransportConfig =\n | StdioTransportConfig\n | StreamableHttpTransportConfig\n | SseTransportConfig;\n\n/**\n * Builds the SDK transport object for a single upstream MCP entry. For HTTP-based\n * transports the factory also constructs a {@link ProxyOAuthProvider} and wires it\n * into the transport, so OAuth-protected upstreams transparently use cached tokens\n * from the keychain and silently refresh as needed. See SPEC.md § \"Upstream OAuth >\n * Proxy Runtime Behavior\".\n *\n * The provider is constructed unconditionally for HTTP / SSE transports. When the\n * upstream does not require OAuth at all, the provider's empty token state means the\n * SDK simply doesn't attach an `Authorization` header — the provider is inert. When\n * the upstream does require OAuth and no credentials are cached, the provider\n * throws {@link AuthRequiredError} with the actionable \"run dynmcp login\" message.\n *\n * @param mcpName the configured MCP name; used for keychain entry naming and error\n * messages. Pass an empty string in tests that don't exercise auth.\n * @param config the validated transport config for one upstream\n */\nexport function createTransport(mcpName: string, config: McpTransportConfig): Transport {\n switch (config.transport) {\n case \"stdio\":\n return new StdioClientTransport({\n command: config.command,\n args: config.args,\n env: config.env,\n });\n\n case \"streamable-http\":\n return new StreamableHTTPClientTransport(new URL(config.url), {\n ...(config.headers !== undefined ? { requestInit: { headers: config.headers } } : {}),\n authProvider: buildOAuthProvider(mcpName, config),\n });\n\n case \"sse\":\n return new SSEClientTransport(new URL(config.url), {\n ...(config.headers !== undefined ? { requestInit: { headers: config.headers } } : {}),\n authProvider: buildOAuthProvider(mcpName, config),\n });\n\n default: {\n const _exhaustive: never = config;\n return _exhaustive;\n }\n }\n}\n\nfunction buildOAuthProvider(\n mcpName: string,\n config: StreamableHttpTransportConfig | SseTransportConfig,\n): ProxyOAuthProvider {\n const keychain = new KeychainStore(mcpName, config.url);\n return new ProxyOAuthProvider(mcpName, keychain, config.auth);\n}\n","import process from \"node:process\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n type CallToolResult,\n type CompleteRequest,\n type CompleteResult,\n type CreateMessageRequest,\n type CreateMessageResult,\n CreateMessageRequestSchema,\n type ElicitRequest,\n type ElicitResult,\n ElicitRequestSchema,\n type GetPromptResult,\n type ListRootsRequest,\n type ListRootsResult,\n ListRootsRequestSchema,\n type LoggingLevel,\n type LoggingMessageNotification,\n LoggingMessageNotificationSchema,\n type Prompt,\n PromptListChangedNotificationSchema,\n type ReadResourceResult,\n type Resource,\n ResourceListChangedNotificationSchema,\n type ResourceTemplate,\n ResourceUpdatedNotificationSchema,\n type ServerCapabilities,\n ToolListChangedNotificationSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type LogMessageParams = LoggingMessageNotification[\"params\"];\n\nexport type ToolAnnotations = {\n title?: string;\n readOnlyHint?: boolean;\n destructiveHint?: boolean;\n idempotentHint?: boolean;\n openWorldHint?: boolean;\n};\n\nexport type UpstreamTool = {\n name: string;\n description: string;\n inputSchema: unknown;\n outputSchema?: unknown;\n annotations?: ToolAnnotations;\n};\n\nexport type UpstreamNotificationHandlers = {\n onToolsListChanged?: () => void | Promise<void>;\n onResourcesListChanged?: () => void | Promise<void>;\n onResourceUpdated?: (params: { uri: string }) => void | Promise<void>;\n onPromptsListChanged?: () => void | Promise<void>;\n onLogMessage?: (params: LogMessageParams) => void | Promise<void>;\n};\n\n/**\n * Progress event payload as observed on a forward-direction call. The SDK Client\n * auto-assigns a progress token for our outbound request, so the upstream's\n * `notifications/progress` for that request are routed here. The proxy translates\n * these into a fresh `notifications/progress` to the host under the host's original\n * progress token.\n */\nexport type ProgressEvent = {\n progress: number;\n total?: number;\n message?: string;\n};\n\n/**\n * Per-call options forwarded to the SDK so cancellation and progress can propagate\n * from the host down to the upstream MCP and back.\n *\n * - `signal`: aborting the host's incoming request aborts this signal, which causes\n * the SDK client to emit `notifications/cancelled` to the upstream.\n * - `onprogress`: invoked whenever the upstream emits a progress notification for\n * the in-flight request. The proxy translates these into host-facing progress\n * notifications under the host's original progress token.\n */\nexport type UpstreamCallOptions = {\n signal?: AbortSignal;\n onprogress?: (progress: ProgressEvent) => void;\n};\n\n/**\n * Reverse-direction handlers invoked when an upstream MCP sends a server-initiated\n * request to the proxy (e.g. `sampling/createMessage`). The proxy forwards each\n * request to the host via these callbacks; the host's response is returned to the\n * originating upstream by the SDK.\n *\n * The `signal` parameter is the upstream's request abort signal — passing it through\n * to the host call causes the host's request to be cancelled if the upstream cancels.\n */\nexport type UpstreamServerRequestHandlers = {\n onCreateMessage?: (\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<CreateMessageResult>;\n onElicitInput?: (\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ElicitResult>;\n onListRoots?: (\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ListRootsResult>;\n};\n\ntype UpstreamClientConfig = {\n name: string;\n transport: Transport;\n onTransportError?: (error: Error) => void;\n notifications?: UpstreamNotificationHandlers;\n serverRequests?: UpstreamServerRequestHandlers;\n};\n\nexport class UpstreamClient {\n private readonly transport: Transport;\n private readonly onTransportError: (error: Error) => void;\n private readonly notificationHandlers: UpstreamNotificationHandlers;\n private readonly serverRequestHandlers: UpstreamServerRequestHandlers;\n private client: Client | null = null;\n\n constructor({\n name,\n transport,\n onTransportError,\n notifications,\n serverRequests,\n }: UpstreamClientConfig) {\n this.transport = transport;\n this.notificationHandlers = notifications ?? {};\n this.serverRequestHandlers = serverRequests ?? {};\n this.onTransportError =\n onTransportError ??\n ((error: Error) => {\n process.stderr.write(`[${name}] Upstream MCP transport error: ${error.message}\\n`);\n });\n }\n\n async connect(): Promise<void> {\n this.transport.onerror = this.onTransportError;\n this.client = new Client(\n { name: \"dynamic-discovery-mcp\", version: \"1.0.0\" },\n {\n capabilities: {\n // Declare every client-side capability the proxy may relay on behalf of the host.\n // Actual reachability of each feature depends on what the host supports — if the\n // host does not support sampling, for instance, the host call returns an error\n // which we forward back to the upstream verbatim.\n sampling: {},\n elicitation: {},\n roots: { listChanged: true },\n },\n },\n );\n\n this.registerServerRequestHandlers(this.client);\n\n if (this.notificationHandlers.onToolsListChanged !== undefined) {\n this.client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {\n await this.notificationHandlers.onToolsListChanged?.();\n });\n }\n if (this.notificationHandlers.onResourcesListChanged !== undefined) {\n this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async () => {\n await this.notificationHandlers.onResourcesListChanged?.();\n });\n }\n if (this.notificationHandlers.onResourceUpdated !== undefined) {\n this.client.setNotificationHandler(ResourceUpdatedNotificationSchema, async notification => {\n await this.notificationHandlers.onResourceUpdated?.({ uri: notification.params.uri });\n });\n }\n if (this.notificationHandlers.onPromptsListChanged !== undefined) {\n this.client.setNotificationHandler(PromptListChangedNotificationSchema, async () => {\n await this.notificationHandlers.onPromptsListChanged?.();\n });\n }\n if (this.notificationHandlers.onLogMessage !== undefined) {\n this.client.setNotificationHandler(LoggingMessageNotificationSchema, async notification => {\n await this.notificationHandlers.onLogMessage?.(notification.params);\n });\n }\n\n await this.client.connect(this.transport);\n }\n\n async setLoggingLevel(level: LoggingLevel, options?: UpstreamCallOptions): Promise<void> {\n const client = this.requireClient();\n await client.setLoggingLevel(level, options);\n }\n\n async listPrompts(options?: UpstreamCallOptions): Promise<Prompt[]> {\n const client = this.requireClient();\n const result = await client.listPrompts(undefined, options);\n return result.prompts;\n }\n\n async getPrompt(\n name: string,\n args?: Record<string, string>,\n options?: UpstreamCallOptions,\n ): Promise<GetPromptResult> {\n const client = this.requireClient();\n const params: { name: string; arguments?: Record<string, string> } = { name };\n if (args !== undefined) {\n params.arguments = args;\n }\n return client.getPrompt(params, options);\n }\n\n async complete(\n params: CompleteRequest[\"params\"],\n options?: UpstreamCallOptions,\n ): Promise<CompleteResult> {\n const client = this.requireClient();\n return client.complete(params, options);\n }\n\n /**\n * Returns the capabilities advertised by the upstream server during initialize.\n * Returns `undefined` if the client is not connected, or if the SDK has not yet\n * recorded the server's capabilities (e.g. during a partially-completed handshake).\n */\n getCapabilities(): ServerCapabilities | undefined {\n return this.client?.getServerCapabilities();\n }\n\n async listTools(options?: UpstreamCallOptions): Promise<UpstreamTool[]> {\n const client = this.requireClient();\n const result = await client.listTools(undefined, options);\n\n return result.tools.map(tool => {\n const upstreamTool: UpstreamTool = {\n name: tool.name,\n description: tool.description ?? \"\",\n inputSchema: tool.inputSchema,\n };\n\n if (tool.outputSchema !== undefined) {\n upstreamTool.outputSchema = tool.outputSchema;\n }\n\n if (tool.annotations !== undefined) {\n upstreamTool.annotations = {\n title: tool.annotations.title,\n readOnlyHint: tool.annotations.readOnlyHint,\n destructiveHint: tool.annotations.destructiveHint,\n idempotentHint: tool.annotations.idempotentHint,\n openWorldHint: tool.annotations.openWorldHint,\n };\n }\n\n return upstreamTool;\n });\n }\n\n async callTool(\n name: string,\n input: Record<string, unknown>,\n options?: UpstreamCallOptions,\n ): Promise<CallToolResult> {\n const client = this.requireClient();\n const result = await client.callTool({ name, arguments: input }, undefined, options);\n return result as CallToolResult;\n }\n\n async listResources(options?: UpstreamCallOptions): Promise<Resource[]> {\n const client = this.requireClient();\n const result = await client.listResources(undefined, options);\n return result.resources;\n }\n\n async listResourceTemplates(options?: UpstreamCallOptions): Promise<ResourceTemplate[]> {\n const client = this.requireClient();\n const result = await client.listResourceTemplates(undefined, options);\n return result.resourceTemplates;\n }\n\n async readResource(uri: string, options?: UpstreamCallOptions): Promise<ReadResourceResult> {\n const client = this.requireClient();\n return client.readResource({ uri }, options);\n }\n\n async subscribeResource(uri: string, options?: UpstreamCallOptions): Promise<void> {\n const client = this.requireClient();\n await client.subscribeResource({ uri }, options);\n }\n\n async unsubscribeResource(uri: string, options?: UpstreamCallOptions): Promise<void> {\n const client = this.requireClient();\n await client.unsubscribeResource({ uri }, options);\n }\n\n async disconnect(): Promise<void> {\n if (this.client === null) {\n return;\n }\n\n await this.client.close();\n this.client = null;\n }\n\n /**\n * Sends `notifications/roots/list_changed` to the upstream, letting it know that\n * the host's set of filesystem roots has changed.\n */\n async sendRootsListChanged(): Promise<void> {\n const client = this.requireClient();\n await client.sendRootsListChanged();\n }\n\n private registerServerRequestHandlers(client: Client): void {\n if (this.serverRequestHandlers.onCreateMessage !== undefined) {\n client.setRequestHandler(\n CreateMessageRequestSchema,\n async (request, extra): Promise<CreateMessageResult> => {\n return this.serverRequestHandlers.onCreateMessage!(request.params, {\n signal: extra.signal,\n });\n },\n );\n }\n if (this.serverRequestHandlers.onElicitInput !== undefined) {\n client.setRequestHandler(\n ElicitRequestSchema,\n async (request, extra): Promise<ElicitResult> => {\n return this.serverRequestHandlers.onElicitInput!(request.params, {\n signal: extra.signal,\n });\n },\n );\n }\n if (this.serverRequestHandlers.onListRoots !== undefined) {\n client.setRequestHandler(\n ListRootsRequestSchema,\n async (request, extra): Promise<ListRootsResult> => {\n return this.serverRequestHandlers.onListRoots!(request.params, {\n signal: extra.signal,\n });\n },\n );\n }\n }\n\n private requireClient(): Client {\n if (this.client === null) {\n throw new Error(\"Client is not connected. Call connect() first.\");\n }\n return this.client;\n }\n}\n","import process from \"node:process\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { loadConfig } from \"../config/index.js\";\nimport { type EagerMcpConfig, type LazyMcpConfig, Orchestrator } from \"./orchestrator.js\";\nimport { ProxyServer } from \"./server.js\";\nimport { createTransport } from \"./transport-factory.js\";\n\nconst SINGLE_MCP_NAME = \"__default__\";\n\nexport async function startProxy(command: string, args: string[]): Promise<void> {\n const transport = new StdioClientTransport({ command, args });\n const eagerMcps = new Map<string, EagerMcpConfig>([[SINGLE_MCP_NAME, { transport }]]);\n\n const orchestrator = buildOrchestrator({\n eagerMcps,\n namespaced: false,\n transportErrorPrefix: () => \"Upstream MCP\",\n });\n\n await runProxy(orchestrator);\n}\n\nexport interface StartProxyFromConfigOptions {\n configPath?: string;\n envFilePath?: string;\n}\n\nexport async function startProxyFromConfig(\n options: StartProxyFromConfigOptions = {},\n): Promise<void> {\n const config = loadConfig(options);\n\n // Partition by `description` presence: entries with a description become lazy\n // upstreams (deferred connection, dynamic discovery enabled); the rest are eager.\n // Order within each partition preserves config-file order.\n const eagerMcps = new Map<string, EagerMcpConfig>();\n const lazyMcps = new Map<string, LazyMcpConfig>();\n for (const [name, entry] of Object.entries(config.mcp)) {\n const transport = createTransport(name, entry);\n if (entry.description !== undefined) {\n lazyMcps.set(name, { transport, description: entry.description });\n } else {\n eagerMcps.set(name, { transport });\n }\n }\n\n const orchestrator = buildOrchestrator({\n eagerMcps,\n lazyMcps,\n namespaced: true,\n transportErrorPrefix: mcpName => `Upstream MCP \"${mcpName}\"`,\n });\n\n await runProxy(orchestrator);\n}\n\ntype BuildOrchestratorParams = {\n eagerMcps: Map<string, EagerMcpConfig>;\n lazyMcps?: Map<string, LazyMcpConfig>;\n namespaced: boolean;\n transportErrorPrefix: (mcpName: string) => string;\n};\n\n// Forward declaration so buildOrchestrator can reference the shutdown closure constructed\n// inside runProxy. Each invocation of runProxy installs its own shutdown function on this\n// holder before the orchestrator's transport-error callbacks can fire.\ntype ShutdownHolder = { shutdown: ((code: number) => void) | null };\n\nconst activeShutdown: ShutdownHolder = { shutdown: null };\n\nfunction buildOrchestrator(params: BuildOrchestratorParams): Orchestrator {\n return new Orchestrator({\n eagerMcps: params.eagerMcps,\n lazyMcps: params.lazyMcps,\n namespaced: params.namespaced,\n onTransportError: (mcpName: string, error: Error) => {\n process.stderr.write(\n `${params.transportErrorPrefix(mcpName)} transport error: ${error.message}\\n`,\n );\n activeShutdown.shutdown?.(1);\n },\n });\n}\n\nasync function runProxy(orchestrator: Orchestrator): Promise<void> {\n let isShuttingDown = false;\n\n const shutdown = (exitCode: number): void => {\n if (isShuttingDown) return;\n isShuttingDown = true;\n\n orchestrator\n .disconnectAll()\n .catch((error: unknown) => {\n process.stderr.write(\n `dynmcp: error during disconnect: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n })\n .finally(() => process.exit(exitCode));\n };\n\n activeShutdown.shutdown = shutdown;\n\n try {\n await orchestrator.connect();\n } catch (error) {\n process.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n return;\n }\n\n const proxyServer = new ProxyServer({\n catalog: () => orchestrator.catalog,\n capabilities: orchestrator.capabilities,\n callTool: (name, input, options) => orchestrator.callTool(name, input, options),\n resources:\n orchestrator.capabilities.resources !== undefined\n ? {\n listResources: () => orchestrator.listResources(),\n listResourceTemplates: () => orchestrator.listResourceTemplates(),\n readResource: (uri, options) => orchestrator.readResource(uri, options),\n subscribeResource: (uri, options) => orchestrator.subscribeResource(uri, options),\n unsubscribeResource: (uri, options) => orchestrator.unsubscribeResource(uri, options),\n }\n : undefined,\n prompts:\n orchestrator.capabilities.prompts !== undefined\n ? {\n listPrompts: () => orchestrator.listPrompts(),\n getPrompt: (name, args, options) => orchestrator.getPrompt(name, args, options),\n }\n : undefined,\n complete:\n orchestrator.capabilities.completions !== undefined\n ? (params, options) => orchestrator.complete(params, options)\n : undefined,\n setLoggingLevel:\n orchestrator.capabilities.logging !== undefined\n ? (level, options) => orchestrator.setLoggingLevel(level, options)\n : undefined,\n onRootsListChanged: () => orchestrator.broadcastRootsListChanged(),\n // Only register the `load_mcp` meta-tool when dynamic discovery is enabled —\n // i.e. when the config declared at least one lazy upstream MCP.\n loadMcp: orchestrator.hasDynamicDiscovery\n ? mcpName => orchestrator.loadMcp(mcpName)\n : undefined,\n });\n\n orchestrator.setNotificationHandlers({\n onToolsListChanged: () => proxyServer.sendToolListChanged(),\n onResourcesListChanged: () => proxyServer.sendResourceListChanged(),\n onResourceUpdated: params => proxyServer.sendResourceUpdated(params),\n onPromptsListChanged: () => proxyServer.sendPromptListChanged(),\n onLogMessage: params => proxyServer.sendLoggingMessage(params),\n });\n\n orchestrator.setServerRequestForwarders({\n onCreateMessage: (params, options) => proxyServer.forwardCreateMessage(params, options),\n onElicitInput: (params, options) => proxyServer.forwardElicitInput(params, options),\n onListRoots: (params, options) => proxyServer.forwardListRoots(params, options),\n });\n\n process.on(\"SIGINT\", () => shutdown(0));\n process.on(\"SIGTERM\", () => shutdown(0));\n process.stdin.on(\"end\", () => shutdown(0));\n process.stdin.on(\"close\", () => shutdown(0));\n\n try {\n await proxyServer.start();\n } catch (error) {\n shutdown(1);\n throw error;\n }\n}\n","import process from \"node:process\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { isAuthRequiredError } from \"../auth/index.js\";\nimport type {\n CallToolResult,\n CompleteRequest,\n CompleteResult,\n CreateMessageRequest,\n CreateMessageResult,\n ElicitRequest,\n ElicitResult,\n GetPromptResult,\n ListRootsRequest,\n ListRootsResult,\n LoggingLevel,\n Prompt,\n ReadResourceResult,\n Resource,\n ResourceTemplate,\n ServerCapabilities,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { aggregateCapabilities } from \"./capability-aggregator.js\";\nimport { LazyRegistry } from \"./lazy-registry.js\";\nimport { NotificationForwarder, type HostNotificationHandlers } from \"./notification-forwarder.js\";\nimport { PromptRouter } from \"./prompt-router.js\";\nimport { ResourceRouter } from \"./resource-router.js\";\nimport { ToolCatalog } from \"./tool-catalog.js\";\nimport type { UpstreamCallOptions, UpstreamClient, UpstreamTool } from \"./upstream-client.js\";\nimport { UpstreamRegistry, type UpstreamConfig } from \"./upstream-registry.js\";\n\nexport type CallOptions = UpstreamCallOptions;\n\nexport type EagerMcpConfig = { transport: Transport };\nexport type LazyMcpConfig = { transport: Transport; description: string };\n\nexport type OrchestratorConfig = {\n /**\n * Upstream MCPs to connect eagerly at startup. In single-MCP (`--`) mode this must\n * contain exactly one entry and `namespaced` must be false.\n */\n eagerMcps: Map<string, EagerMcpConfig>;\n /**\n * Optional lazy upstream MCPs — those declared with a `description` field. Connection\n * is deferred until `loadMcp(name)` is called. The presence of any lazy entry enables\n * dynamic discovery (see SPEC.md § \"Dynamic Discovery\"). Must be empty in single-MCP\n * mode.\n *\n * The iteration order is preserved (config-file order) and is also used for router\n * priority alongside the eager entries — eager names come first, then lazy names, all\n * in their original config-file order.\n */\n lazyMcps?: Map<string, LazyMcpConfig>;\n /**\n * When true (config-file mode), tools are exposed as `<mcpName>/<toolName>` and routed\n * by splitting on the first `/`. When false (single-MCP `--` mode), tools are exposed\n * as bare names and routed to the sole upstream client.\n */\n namespaced: boolean;\n onTransportError?: (mcpName: string, error: Error) => void;\n};\n\n/**\n * Maximum consecutive failed `load_mcp` attempts per lazy MCP before the entry is\n * evicted from {@link LazyRegistry}. Once evicted, the agent receives \"unknown\n * server\" responses on subsequent calls and the entry vanishes from the\n * `<mcp_servers>` block. Three strikes is a balance: transient network or\n * startup hiccups are tolerated, but a permanently broken upstream stops burning\n * agent context forever.\n */\nexport const MAX_LOAD_ATTEMPTS = 3;\n\n/**\n * Structured response returned by {@link Orchestrator.loadMcp}. Mirrors the schema\n * documented in SPEC.md for `load_mcp`'s output. Tool schemas are deliberately omitted\n * — `discover_tool` still owns the schema-retrieval surface; this listing is the\n * \"what's in here\" overview that lets the agent navigate post-load.\n */\nexport type LoadMcpResult = {\n mcp_name: string;\n tools: Array<{ name: string; description: string }>;\n resources: Array<{\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n }>;\n resource_templates: Array<{\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n }>;\n prompts: Array<{\n name: string;\n description?: string;\n arguments?: Prompt[\"arguments\"];\n }>;\n};\n\nexport type OrchestratorNotificationHandlers = HostNotificationHandlers;\n\n/**\n * Forwarders for upstream-initiated requests. The Orchestrator wires each upstream\n * client's incoming request handlers to call into these so the proxy can relay the\n * request to the host. `signal` is the upstream's request-abort signal — passing it\n * through to the host call propagates cancellation if the upstream cancels.\n */\nexport type OrchestratorServerRequestForwarders = {\n onCreateMessage?: (\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<CreateMessageResult>;\n onElicitInput?: (\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ElicitResult>;\n onListRoots?: (\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ) => Promise<ListRootsResult>;\n};\n\n/**\n * Composition root for the proxy hub. Composes {@link UpstreamRegistry} (lifecycle),\n * {@link NotificationForwarder} (upstream→host notification translation), and the\n * routers/catalogs (forward-direction request routing). Public surface is the same\n * across single-MCP and config-file modes; the `namespaced` flag toggles tool-naming\n * behavior internally.\n */\nexport class Orchestrator {\n private readonly config: OrchestratorConfig;\n private readonly registry: UpstreamRegistry = new UpstreamRegistry();\n private readonly lazyRegistry: LazyRegistry = new LazyRegistry();\n private readonly toolsByMcp: Map<string, UpstreamTool[]> = new Map();\n /**\n * In-flight loads, keyed by mcpName. Used by {@link loadMcp} to coalesce concurrent\n * calls for the same name onto a single underlying connection attempt — per SPEC.md\n * § \"Dynamic Discovery > Concurrency\".\n */\n private readonly inFlightLoads: Map<string, Promise<LoadMcpResult>> = new Map();\n private resourceRouter: ResourceRouter | null = null;\n private promptRouter: PromptRouter | null = null;\n private toolCatalog: ToolCatalog | null = null;\n private aggregatedCapabilities: ServerCapabilities | null = null;\n private serverRequestForwarders: OrchestratorServerRequestForwarders = {};\n private readonly forwarder: NotificationForwarder;\n\n constructor(config: OrchestratorConfig) {\n if (!config.namespaced && config.eagerMcps.size !== 1) {\n throw new Error(\n `Single-MCP (non-namespaced) mode requires exactly one upstream; got ${config.eagerMcps.size}.`,\n );\n }\n if (!config.namespaced && config.lazyMcps !== undefined && config.lazyMcps.size > 0) {\n throw new Error(\n \"Single-MCP (non-namespaced) mode does not support lazy upstreams (descriptions).\",\n );\n }\n this.config = config;\n this.forwarder = new NotificationForwarder(\n this.registry,\n () => this.resourceRouter,\n () => this.promptRouter,\n this.toolsByMcp,\n () => this.rebuildToolCatalog(),\n this.config.namespaced,\n );\n }\n\n setNotificationHandlers(handlers: OrchestratorNotificationHandlers): void {\n this.forwarder.setHostHandlers(handlers);\n }\n\n setServerRequestForwarders(forwarders: OrchestratorServerRequestForwarders): void {\n this.serverRequestForwarders = forwarders;\n }\n\n /**\n * True when the orchestrator was configured with at least one lazy upstream MCP.\n * The `index.ts` wiring uses this to decide whether to register the `load_mcp`\n * meta-tool with the host-facing {@link ProxyServer}.\n */\n get hasDynamicDiscovery(): boolean {\n return this.config.lazyMcps !== undefined && this.config.lazyMcps.size > 0;\n }\n\n async connect(): Promise<void> {\n // Router priority order includes lazy names too — eager entries populate now, lazy\n // entries populate as `loadMcp` calls land. This way first-wins collision rules\n // are defined entirely by config-file order and don't shift around when a lazy MCP\n // joins later.\n const allNames = [...this.config.eagerMcps.keys(), ...(this.config.lazyMcps?.keys() ?? [])];\n const resourceRouter = new ResourceRouter(allNames);\n const promptRouter = new PromptRouter(allNames);\n\n if (this.config.lazyMcps !== undefined) {\n for (const [name, { transport, description }] of this.config.lazyMcps) {\n this.lazyRegistry.register(name, { transport, description });\n }\n }\n\n const upstreamEntries: ReadonlyArray<readonly [string, UpstreamConfig]> = [\n ...this.config.eagerMcps,\n ].map(([mcpName, { transport }]) => [mcpName, this.buildUpstreamConfig(mcpName, transport)]);\n\n await this.registry.connectAll(upstreamEntries);\n\n const capabilityList: (ServerCapabilities | undefined)[] = [];\n this.toolsByMcp.clear();\n\n for (const [mcpName, client] of this.registry.entries()) {\n const caps = client.getCapabilities();\n capabilityList.push(caps);\n\n const tools = await client.listTools();\n this.toolsByMcp.set(mcpName, tools);\n\n if (caps?.resources !== undefined) {\n const [resources, templates] = await Promise.all([\n client.listResources().catch(() => [] as Resource[]),\n client.listResourceTemplates().catch(() => [] as ResourceTemplate[]),\n ]);\n resourceRouter.setResources(mcpName, resources);\n resourceRouter.setTemplates(mcpName, templates);\n }\n if (caps?.prompts !== undefined) {\n const prompts = await client.listPrompts().catch(() => [] as Prompt[]);\n promptRouter.setPrompts(mcpName, prompts);\n }\n }\n\n this.resourceRouter = resourceRouter;\n this.promptRouter = promptRouter;\n this.aggregatedCapabilities = aggregateCapabilities(capabilityList);\n this.rebuildToolCatalog();\n\n logCollisions(resourceRouter, promptRouter);\n }\n\n async disconnectAll(): Promise<void> {\n await this.registry.disconnectAll();\n this.toolsByMcp.clear();\n this.toolCatalog = null;\n this.aggregatedCapabilities = null;\n this.resourceRouter = null;\n this.promptRouter = null;\n this.inFlightLoads.clear();\n }\n\n // === Dynamic discovery ===\n\n /**\n * Loads a lazy upstream MCP on demand. Implements the semantics of SPEC.md §\n * \"Tools > load_mcp\" and § \"Dynamic Discovery > Lifecycle of a Lazy MCP\":\n *\n * - Already-loaded (eager or previously-loaded lazy) names succeed as a no-op\n * returning the current listing; no notifications fire.\n * - Unknown names throw an error that hints at the still-lazy alternatives.\n * - Concurrent calls for the same name coalesce onto the same in-flight load.\n * - A failure during connect/initialize/catalog-query rolls back atomically:\n * the upstream is disconnected, the lazy entry stays registered, no host\n * notifications fire.\n * - On success the loaded MCP is promoted into the connected registry, its\n * tools/resources/prompts populate the routers, the discover_tool catalog\n * is regenerated, and the host receives `tools/list_changed` plus\n * `resources/list_changed` and/or `prompts/list_changed` for any non-empty\n * surface the MCP contributed.\n */\n async loadMcp(mcpName: string): Promise<LoadMcpResult> {\n if (this.registry.get(mcpName) !== undefined) {\n // Already connected — either eager at startup or previously loaded. Idempotent\n // no-op: return current listing without firing notifications.\n return this.getListing(mcpName);\n }\n\n const inFlight = this.inFlightLoads.get(mcpName);\n if (inFlight !== undefined) {\n return inFlight;\n }\n\n if (!this.lazyRegistry.has(mcpName)) {\n const lazyNames = this.lazyRegistry.names().join(\", \");\n const hint = lazyNames.length > 0 ? lazyNames : \"(none)\";\n throw new Error(`Unknown MCP server: \"${mcpName}\". Available servers to load: ${hint}`);\n }\n\n const loadPromise = this.runLoadPipeline(mcpName).finally(() => {\n this.inFlightLoads.delete(mcpName);\n });\n this.inFlightLoads.set(mcpName, loadPromise);\n return loadPromise;\n }\n\n private async runLoadPipeline(mcpName: string): Promise<LoadMcpResult> {\n const entry = this.lazyRegistry.get(mcpName);\n if (entry === undefined) {\n throw new Error(`Internal error: lazy entry \"${mcpName}\" vanished mid-load.`);\n }\n\n const client = await this.registry.connectOne(\n mcpName,\n this.buildUpstreamConfig(mcpName, entry.transport),\n );\n\n let tools: UpstreamTool[];\n let resources: Resource[] = [];\n let templates: ResourceTemplate[] = [];\n let prompts: Prompt[] = [];\n let caps: ServerCapabilities | undefined;\n try {\n caps = client.getCapabilities();\n tools = await client.listTools();\n\n if (caps?.resources !== undefined) {\n [resources, templates] = await Promise.all([\n client.listResources(),\n client.listResourceTemplates(),\n ]);\n }\n if (caps?.prompts !== undefined) {\n prompts = await client.listPrompts();\n }\n } catch (error) {\n // Roll back atomically: drop the half-loaded upstream. Auth-required failures\n // are operator-actionable (user must run `dynmcp login`), not transient —\n // counting them toward the retry budget would silently evict the MCP before\n // the user can act. The lazy entry stays registered for unlimited retries\n // until the user completes the login flow. See SPEC.md § \"Upstream OAuth >\n // Proxy Runtime Behavior\".\n await this.registry.deleteOne(mcpName);\n if (isAuthRequiredError(error)) {\n throw error;\n }\n // All other failures count against the retry budget. Once exhausted, evict\n // the lazy entry entirely and emit `tools/list_changed` so the host sees\n // `<mcp_servers>` update.\n const failures = this.lazyRegistry.recordFailure(mcpName);\n if (failures >= MAX_LOAD_ATTEMPTS) {\n this.lazyRegistry.take(mcpName);\n this.rebuildToolCatalog();\n await this.forwarder.notifyToolsListChanged();\n const base = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Failed to load \"${mcpName}\" after ${failures} attempts; the server will no longer be offered for discovery. Underlying error: ${base}`,\n );\n }\n throw error;\n }\n\n // Commit phase: from here on every step is purely local mutation, so the load is\n // atomic in practice — we've succeeded in talking to the upstream, and updating\n // local state cannot fail in a way that leaves us with a phantom load.\n this.lazyRegistry.take(mcpName);\n this.toolsByMcp.set(mcpName, tools);\n const resourceRouter = this.requireResourceRouter();\n const promptRouter = this.requirePromptRouter();\n if (caps?.resources !== undefined) {\n resourceRouter.setResources(mcpName, resources);\n resourceRouter.setTemplates(mcpName, templates);\n }\n if (caps?.prompts !== undefined) {\n promptRouter.setPrompts(mcpName, prompts);\n }\n this.rebuildToolCatalog();\n\n // Emit notifications. `tools/list_changed` always — the catalog and the\n // `<mcp_servers>` block both changed. Resource/prompt notifications are emitted\n // only when the MCP contributed entries (per SPEC.md § \"load_mcp\").\n await this.forwarder.notifyToolsListChanged();\n if (caps?.resources !== undefined && (resources.length > 0 || templates.length > 0)) {\n await this.forwarder.notifyResourcesListChanged();\n }\n if (caps?.prompts !== undefined && prompts.length > 0) {\n await this.forwarder.notifyPromptsListChanged();\n }\n\n return this.getListing(mcpName);\n }\n\n /**\n * Builds the structured response shape documented for `load_mcp` from existing\n * per-MCP state. Pulled out into a helper so the no-op path (already-loaded)\n * and the success path share one source of truth.\n */\n private getListing(mcpName: string): LoadMcpResult {\n const tools = this.toolsByMcp.get(mcpName) ?? [];\n const namespacedToolName = (name: string): string =>\n this.config.namespaced ? `${mcpName}/${name}` : name;\n\n const resources = this.resourceRouter?.resourcesFor(mcpName) ?? [];\n const templates = this.resourceRouter?.templatesFor(mcpName) ?? [];\n const prompts = this.promptRouter?.promptsFor(mcpName) ?? [];\n\n return {\n mcp_name: mcpName,\n tools: tools.map(tool => ({\n name: namespacedToolName(tool.name),\n description: tool.description,\n })),\n resources: resources.map(resource => ({\n uri: resource.uri,\n name: resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n })),\n resource_templates: templates.map(template => ({\n uriTemplate: template.uriTemplate,\n name: template.name,\n description: template.description,\n mimeType: template.mimeType,\n })),\n prompts: prompts.map(prompt => ({\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n })),\n };\n }\n\n // === Internal helpers used by connect() and loadMcp() ===\n\n private buildUpstreamConfig(mcpName: string, transport: Transport): UpstreamConfig {\n return {\n transport,\n onTransportError: (error: Error) => {\n this.config.onTransportError?.(mcpName, error);\n },\n notifications: {\n onToolsListChanged: () => this.forwarder.handleToolsListChanged(mcpName),\n onResourcesListChanged: () => this.forwarder.handleResourcesListChanged(mcpName),\n onResourceUpdated: params => this.forwarder.handleResourceUpdated(params),\n onPromptsListChanged: () => this.forwarder.handlePromptsListChanged(mcpName),\n onLogMessage: params => this.forwarder.handleLogMessage(mcpName, params),\n },\n serverRequests: {\n onCreateMessage: (params, opts) => this.forwardCreateMessage(params, opts),\n onElicitInput: (params, opts) => this.forwardElicitInput(params, opts),\n onListRoots: (params, opts) => this.forwardListRoots(params, opts),\n },\n };\n }\n\n /**\n * Rebuilds the `ToolCatalog` from current state. Called whenever `toolsByMcp` or the\n * lazy-registry membership changes — including initial connect, upstream-emitted\n * `tools/list_changed`, and successful `loadMcp`.\n */\n private rebuildToolCatalog(): void {\n if (this.config.namespaced) {\n this.toolCatalog = ToolCatalog.fromGroupedWithLazy(\n this.toolsByMcp,\n this.lazyRegistry.descriptions(),\n );\n } else {\n this.toolCatalog = ToolCatalog.fromFlat([...this.toolsByMcp.values()][0] ?? []);\n }\n }\n\n get catalog(): ToolCatalog {\n if (this.toolCatalog === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.toolCatalog;\n }\n\n get capabilities(): ServerCapabilities {\n if (this.aggregatedCapabilities === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.aggregatedCapabilities;\n }\n\n // === Forward-direction request routing ===\n\n async callTool(\n displayName: string,\n input: Record<string, unknown>,\n options?: CallOptions,\n ): Promise<CallToolResult> {\n if (this.config.namespaced) {\n const { mcpName, toolName } = splitNamespacedName(displayName, this.registry.names());\n return this.requireClient(mcpName, \"tool\").callTool(toolName, input, options);\n }\n\n const sole = this.registry.sole();\n if (sole === undefined) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return sole.callTool(displayName, input, options);\n }\n\n listResources(): Resource[] {\n return this.requireResourceRouter().aggregatedResources();\n }\n\n listResourceTemplates(): ResourceTemplate[] {\n return this.requireResourceRouter().aggregatedTemplates();\n }\n\n async readResource(uri: string, options?: CallOptions): Promise<ReadResourceResult> {\n return this.resolveResourceOwner(uri).readResource(uri, options);\n }\n\n async subscribeResource(uri: string, options?: CallOptions): Promise<void> {\n await this.resolveResourceOwner(uri).subscribeResource(uri, options);\n }\n\n async unsubscribeResource(uri: string, options?: CallOptions): Promise<void> {\n await this.resolveResourceOwner(uri).unsubscribeResource(uri, options);\n }\n\n listPrompts(): Prompt[] {\n return this.requirePromptRouter().aggregatedPrompts();\n }\n\n async getPrompt(\n name: string,\n args?: Record<string, string>,\n options?: CallOptions,\n ): Promise<GetPromptResult> {\n return this.resolvePromptOwner(name).getPrompt(name, args, options);\n }\n\n async complete(\n params: CompleteRequest[\"params\"],\n options?: CallOptions,\n ): Promise<CompleteResult> {\n const client = this.resolveCompletionTarget(params.ref);\n return client.complete(params, options);\n }\n\n // === Broadcasts ===\n\n /**\n * Broadcasts a `logging/setLevel` request to every upstream advertising the logging\n * capability. Errors from individual upstreams are swallowed so a single misbehaving\n * upstream cannot break the broadcast for others; failures are written to stderr.\n */\n async setLoggingLevel(level: LoggingLevel, options?: CallOptions): Promise<void> {\n await this.broadcastAsync(\n client =>\n client.getCapabilities()?.logging !== undefined\n ? client.setLoggingLevel(level, options)\n : Promise.resolve(),\n \"setLoggingLevel\",\n );\n }\n\n /**\n * Broadcasts `notifications/roots/list_changed` to every connected upstream — the\n * proxy declares roots capability uniformly to all upstreams so every one of them\n * may have requested roots and needs to know the list changed.\n */\n async broadcastRootsListChanged(): Promise<void> {\n await this.broadcastAsync(client => client.sendRootsListChanged(), \"sendRootsListChanged\");\n }\n\n // === Server-initiated request forwarders (upstream → host) ===\n\n private async forwardCreateMessage(\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<CreateMessageResult> {\n const handler = this.serverRequestForwarders.onCreateMessage;\n if (handler === undefined) {\n throw new Error(\"Proxy does not support sampling: host has not registered a handler.\");\n }\n return handler(params, options);\n }\n\n private async forwardElicitInput(\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ElicitResult> {\n const handler = this.serverRequestForwarders.onElicitInput;\n if (handler === undefined) {\n throw new Error(\"Proxy does not support elicitation: host has not registered a handler.\");\n }\n return handler(params, options);\n }\n\n private async forwardListRoots(\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ListRootsResult> {\n const handler = this.serverRequestForwarders.onListRoots;\n if (handler === undefined) {\n throw new Error(\"Proxy does not support roots: host has not registered a handler.\");\n }\n return handler(params, options);\n }\n\n // === Internal helpers ===\n\n private requireResourceRouter(): ResourceRouter {\n if (this.resourceRouter === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.resourceRouter;\n }\n\n private requirePromptRouter(): PromptRouter {\n if (this.promptRouter === null) {\n throw new Error(\"Orchestrator is not connected. Call connect() first.\");\n }\n return this.promptRouter;\n }\n\n private resolveResourceOwner(uri: string): UpstreamClient {\n const owner = this.requireResourceRouter().ownerOf(uri);\n if (owner === undefined) {\n throw new Error(`Unknown resource URI: \"${uri}\". No upstream MCP advertises it.`);\n }\n return this.requireClient(owner, \"resource\");\n }\n\n private resolvePromptOwner(name: string): UpstreamClient {\n const owner = this.requirePromptRouter().ownerOf(name);\n if (owner === undefined) {\n throw new Error(`Unknown prompt: \"${name}\". No upstream MCP advertises it.`);\n }\n return this.requireClient(owner, \"prompt\");\n }\n\n private resolveCompletionTarget(ref: CompleteRequest[\"params\"][\"ref\"]): UpstreamClient {\n if (ref.type === \"ref/prompt\") {\n return this.resolvePromptOwner(ref.name);\n }\n if (ref.type === \"ref/resource\") {\n return this.resolveResourceOwner(ref.uri);\n }\n const unknownRef: { type: string } = ref;\n throw new Error(`Unsupported completion ref type: \"${unknownRef.type}\"`);\n }\n\n private requireClient(mcpName: string, role: string): UpstreamClient {\n const client = this.registry.get(mcpName);\n if (client === undefined) {\n throw new Error(`Internal error: ${role} owner \"${mcpName}\" has no connected client.`);\n }\n return client;\n }\n\n private async broadcastAsync(\n action: (client: UpstreamClient) => Promise<void>,\n label: string,\n ): Promise<void> {\n const targets: Promise<void>[] = [];\n for (const [mcpName, client] of this.registry.entries()) {\n targets.push(\n action(client).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`dynmcp: ${label} failed for \"${mcpName}\": ${message}\\n`);\n }),\n );\n }\n await Promise.all(targets);\n }\n}\n\nfunction splitNamespacedName(\n namespacedName: string,\n knownMcpNames: readonly string[],\n): { mcpName: string; toolName: string } {\n const separatorIndex = namespacedName.indexOf(\"/\");\n if (separatorIndex === -1) {\n throw new Error(\n `Invalid namespaced tool name: \"${namespacedName}\". Expected format: \"mcpName/toolName\".`,\n );\n }\n\n const mcpName = namespacedName.slice(0, separatorIndex);\n const toolName = namespacedName.slice(separatorIndex + 1);\n\n if (!knownMcpNames.includes(mcpName)) {\n const available = [...knownMcpNames].sort().join(\", \");\n throw new Error(`Unknown MCP: \"${mcpName}\". Available MCPs: ${available}`);\n }\n\n return { mcpName, toolName };\n}\n\nfunction logCollisions(resourceRouter: ResourceRouter, promptRouter: PromptRouter): void {\n for (const collision of resourceRouter.collisions()) {\n process.stderr.write(\n `dynmcp: resource URI collision: \"${collision.uri}\" is provided by ` +\n `\"${collision.chosen}\" and \"${collision.shadowed}\"; routing to \"${collision.chosen}\".\\n`,\n );\n }\n for (const collision of promptRouter.collisions()) {\n process.stderr.write(\n `dynmcp: prompt name collision: \"${collision.name}\" is provided by ` +\n `\"${collision.chosen}\" and \"${collision.shadowed}\"; routing to \"${collision.chosen}\".\\n`,\n );\n }\n}\n","import type { ServerCapabilities } from \"@modelcontextprotocol/sdk/types.js\";\n\n/**\n * Aggregates the capabilities advertised by every upstream MCP into the single\n * capability set that the proxy will advertise to the host during `initialize`.\n *\n * Rules (per SPEC.md \"Capability Aggregation\"):\n *\n * - `tools` is always advertised — the proxy itself exposes `discover_tool` and `use_tool`\n * regardless of upstream support.\n * - `tools.listChanged` is always advertised — the proxy emits it when any upstream's tool\n * list changes, even when no individual upstream supports the notification.\n * - All other capabilities (`resources`, `prompts`, `logging`, `completions`) are advertised\n * iff at least one upstream advertises them. Nested booleans (`subscribe`, `listChanged`)\n * are advertised iff at least one supporting upstream advertises them.\n */\nexport function aggregateCapabilities(\n upstreams: ReadonlyArray<ServerCapabilities | undefined>,\n): ServerCapabilities {\n const aggregated: ServerCapabilities = {\n tools: { listChanged: true },\n };\n\n for (const caps of upstreams) {\n if (caps === undefined) continue;\n\n if (caps.resources !== undefined) {\n aggregated.resources ??= {};\n if (caps.resources.subscribe === true) {\n aggregated.resources.subscribe = true;\n }\n if (caps.resources.listChanged === true) {\n aggregated.resources.listChanged = true;\n }\n }\n\n if (caps.prompts !== undefined) {\n aggregated.prompts ??= {};\n if (caps.prompts.listChanged === true) {\n aggregated.prompts.listChanged = true;\n }\n }\n\n if (caps.logging !== undefined) {\n aggregated.logging ??= {};\n }\n\n if (caps.completions !== undefined) {\n aggregated.completions ??= {};\n }\n }\n\n return aggregated;\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\n\n/**\n * One unconnected lazy upstream MCP. Held by {@link LazyRegistry} until a `load_mcp`\n * call promotes it to a connected upstream in the {@link UpstreamRegistry}.\n *\n * The transport is constructed at startup (so a misconfigured transport surfaces\n * before any host traffic arrives) but is not actually opened until load time —\n * {@link UpstreamClient.connect} is what opens the underlying connection.\n */\nexport type LazyEntry = {\n readonly description: string;\n readonly transport: Transport;\n};\n\n/**\n * Stores the lazy-loading-eligible upstream MCPs declared in the config file —\n * those entries that carry a `description` field. The registry preserves the\n * config-file insertion order so the `<mcp_servers>` block in `discover_tool`'s\n * description renders in a stable order matching the user's config.\n *\n * Once a lazy MCP transitions to `loaded` (via the orchestrator's `loadMcp`\n * pipeline), {@link take} is called to remove it from this registry. There is\n * no \"unloaded\" state by design — see SPEC.md § \"Dynamic Discovery > Lifecycle\".\n *\n * Failed loads are tracked per-entry via {@link recordFailure}. After enough\n * consecutive failures the orchestrator will evict the entry — this prevents\n * an agent from burning forever on a broken upstream while still tolerating\n * transient hiccups.\n */\nexport class LazyRegistry {\n private readonly entries: Map<string, LazyEntry> = new Map();\n private readonly failureCounts: Map<string, number> = new Map();\n\n register(name: string, entry: LazyEntry): void {\n if (this.entries.has(name)) {\n throw new Error(`LazyRegistry: duplicate registration for \"${name}\"`);\n }\n this.entries.set(name, entry);\n }\n\n has(name: string): boolean {\n return this.entries.has(name);\n }\n\n get(name: string): LazyEntry | undefined {\n return this.entries.get(name);\n }\n\n /**\n * Records a failed load attempt and returns the new total. The orchestrator's\n * retry-budget logic uses this to decide whether to evict the entry. A\n * subsequent successful load (or {@link take}) clears the count.\n */\n recordFailure(name: string): number {\n const next = (this.failureCounts.get(name) ?? 0) + 1;\n this.failureCounts.set(name, next);\n return next;\n }\n\n failureCount(name: string): number {\n return this.failureCounts.get(name) ?? 0;\n }\n\n /**\n * Returns the descriptions of every still-lazy MCP in insertion order. Consumed\n * by {@link ToolCatalog.fromGroupedWithLazy} to render the `<mcp_servers>` block.\n */\n descriptions(): ReadonlyMap<string, string> {\n const result = new Map<string, string>();\n for (const [name, entry] of this.entries) {\n result.set(name, entry.description);\n }\n return result;\n }\n\n /**\n * Returns the names of every still-lazy MCP in insertion order. Used by error\n * messages that need to hint the agent at what is loadable.\n */\n names(): readonly string[] {\n return [...this.entries.keys()];\n }\n\n size(): number {\n return this.entries.size;\n }\n\n /**\n * Removes and returns the entry, signalling that the upstream has been (or is\n * about to be) promoted to a connected client (or evicted after exhausting\n * its retry budget). The caller is responsible for ensuring the promotion\n * actually succeeds — failed loads should re-register via {@link register} to\n * roll back the state. Clears the failure count along with the entry.\n */\n take(name: string): LazyEntry | undefined {\n const entry = this.entries.get(name);\n if (entry === undefined) return undefined;\n this.entries.delete(name);\n this.failureCounts.delete(name);\n return entry;\n }\n}\n","import type { Prompt, Resource, ResourceTemplate } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { PromptRouter } from \"./prompt-router.js\";\nimport type { ResourceRouter } from \"./resource-router.js\";\nimport type { LogMessageParams, UpstreamTool } from \"./upstream-client.js\";\nimport type { UpstreamRegistry } from \"./upstream-registry.js\";\n\n/**\n * Callbacks the proxy uses to push notifications out to the host once an upstream\n * has emitted the equivalent inbound notification. The {@link NotificationForwarder}\n * is the seam between the upstream-side notification handlers (which it owns) and\n * the host-side outbound calls (which the caller provides).\n */\nexport type HostNotificationHandlers = {\n onToolsListChanged?: () => void | Promise<void>;\n onResourcesListChanged?: () => void | Promise<void>;\n onResourceUpdated?: (params: { uri: string }) => void | Promise<void>;\n onPromptsListChanged?: () => void | Promise<void>;\n onLogMessage?: (params: LogMessageParams) => void | Promise<void>;\n};\n\n/**\n * Translates upstream-emitted notifications into proxy-emitted notifications sent\n * to the host. For list-change notifications this includes re-fetching the affected\n * data from the originating upstream and updating the shared catalogs/routers before\n * propagating the change. For log messages it rewrites the `logger` field with the\n * `<mcp-name>/` prefix in config-file mode.\n *\n * The forwarder holds references to mutable state (the tool catalog, the routers)\n * and is expected to be co-owned with whatever assembles that state — typically the\n * Orchestrator. Catalog rebuilds are performed via the {@link buildToolCatalog}\n * callback so the Orchestrator stays the single owner of the catalog reference.\n */\nexport class NotificationForwarder {\n private hostHandlers: HostNotificationHandlers = {};\n\n constructor(\n private readonly registry: UpstreamRegistry,\n private readonly resourceRouter: () => ResourceRouter | null,\n private readonly promptRouter: () => PromptRouter | null,\n private readonly toolsByMcp: Map<string, UpstreamTool[]>,\n /**\n * Asks the orchestrator to rebuild the tool catalog from current state\n * (`toolsByMcp` plus, when dynamic discovery is enabled, the lazy registry's\n * descriptions). The forwarder doesn't own that composition itself so this stays\n * a single seam.\n */\n private readonly rebuildToolCatalog: () => void,\n private readonly namespaced: boolean,\n ) {}\n\n setHostHandlers(handlers: HostNotificationHandlers): void {\n this.hostHandlers = handlers;\n }\n\n async handleToolsListChanged(mcpName: string): Promise<void> {\n const client = this.registry.get(mcpName);\n if (client === undefined) return;\n\n const tools = await client.listTools().catch(() => [] as UpstreamTool[]);\n this.toolsByMcp.set(mcpName, tools);\n this.rebuildToolCatalog();\n\n await this.hostHandlers.onToolsListChanged?.();\n }\n\n async handleResourcesListChanged(mcpName: string): Promise<void> {\n const router = this.resourceRouter();\n const client = this.registry.get(mcpName);\n if (router === null || client === undefined) return;\n\n const [resources, templates] = await Promise.all([\n client.listResources().catch(() => [] as Resource[]),\n client.listResourceTemplates().catch(() => [] as ResourceTemplate[]),\n ]);\n router.setResources(mcpName, resources);\n router.setTemplates(mcpName, templates);\n\n await this.hostHandlers.onResourcesListChanged?.();\n }\n\n async handleResourceUpdated(params: { uri: string }): Promise<void> {\n await this.hostHandlers.onResourceUpdated?.(params);\n }\n\n /**\n * Fire-only emitters. Unlike `handleXListChanged`, these do not re-fetch the\n * affected data from any upstream — the caller has already populated the relevant\n * state directly. Used by the orchestrator's load_mcp pipeline, which already has\n * the freshly-queried tools/resources/prompts in hand and just needs to nudge the\n * host to refetch.\n */\n async notifyToolsListChanged(): Promise<void> {\n await this.hostHandlers.onToolsListChanged?.();\n }\n\n async notifyResourcesListChanged(): Promise<void> {\n await this.hostHandlers.onResourcesListChanged?.();\n }\n\n async notifyPromptsListChanged(): Promise<void> {\n await this.hostHandlers.onPromptsListChanged?.();\n }\n\n async handlePromptsListChanged(mcpName: string): Promise<void> {\n const router = this.promptRouter();\n const client = this.registry.get(mcpName);\n if (router === null || client === undefined) return;\n\n const prompts = await client.listPrompts().catch(() => [] as Prompt[]);\n router.setPrompts(mcpName, prompts);\n\n await this.hostHandlers.onPromptsListChanged?.();\n }\n\n /**\n * Rewrites the upstream's `logger` field with the originating MCP's name as a\n * prefix so the host can attribute log lines, then forwards the message to the\n * host's log message handler.\n */\n async handleLogMessage(mcpName: string, params: LogMessageParams): Promise<void> {\n const handler = this.hostHandlers.onLogMessage;\n if (handler === undefined) return;\n\n if (!this.namespaced) {\n await handler(params);\n return;\n }\n\n const prefixed: LogMessageParams = {\n ...params,\n logger: params.logger === undefined ? mcpName : `${mcpName}/${params.logger}`,\n };\n await handler(prefixed);\n }\n}\n","import type { Prompt } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type PromptCollision = {\n name: string;\n chosen: string;\n shadowed: string;\n};\n\n/**\n * Tracks which upstream MCP owns each prompt name exposed through the proxy and\n * resolves the owner for any `prompts/get` or `completion/complete` request that\n * references a prompt by name.\n *\n * Collision rule: when two upstreams advertise the same prompt name, the upstream\n * appearing first in config-file order wins; the shadowed upstream's prompt is\n * unreachable through the proxy until the conflict is resolved upstream.\n */\nexport class PromptRouter {\n private readonly mcpOrder: string[];\n private readonly perMcp: Map<string, Prompt[]>;\n\n private nameOwners: Map<string, string> = new Map();\n private detectedCollisions: PromptCollision[] = [];\n\n constructor(mcpOrder: readonly string[]) {\n this.mcpOrder = [...mcpOrder];\n this.perMcp = new Map(this.mcpOrder.map(name => [name, [] as Prompt[]]));\n }\n\n setPrompts(mcpName: string, prompts: Prompt[]): void {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) {\n throw new Error(`PromptRouter: unknown mcp \"${mcpName}\"`);\n }\n this.perMcp.set(mcpName, [...prompts]);\n this.rebuild();\n }\n\n aggregatedPrompts(): Prompt[] {\n const result: Prompt[] = [];\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry !== undefined) {\n result.push(...entry);\n }\n }\n return result;\n }\n\n ownerOf(promptName: string): string | undefined {\n return this.nameOwners.get(promptName);\n }\n\n collisions(): readonly PromptCollision[] {\n return this.detectedCollisions;\n }\n\n /**\n * Returns the prompts contributed by a single upstream MCP. Used by the load_mcp\n * pipeline to construct its structured response. Returns an empty array if the MCP\n * has not contributed any prompts (or if `mcpName` is unknown).\n */\n promptsFor(mcpName: string): readonly Prompt[] {\n return this.perMcp.get(mcpName) ?? [];\n }\n\n private rebuild(): void {\n this.nameOwners = new Map();\n const collisions: PromptCollision[] = [];\n\n for (const mcpName of this.mcpOrder) {\n const prompts = this.perMcp.get(mcpName);\n if (prompts === undefined) continue;\n\n for (const prompt of prompts) {\n const existing = this.nameOwners.get(prompt.name);\n if (existing === undefined) {\n this.nameOwners.set(prompt.name, mcpName);\n } else {\n collisions.push({ name: prompt.name, chosen: existing, shadowed: mcpName });\n }\n }\n }\n\n this.detectedCollisions = collisions;\n }\n}\n","import type { Resource, ResourceTemplate } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type ResourceCollision = {\n uri: string;\n chosen: string;\n shadowed: string;\n};\n\n/**\n * Tracks which upstream MCP owns each resource URI exposed through the proxy and\n * resolves the owner for any `resources/read`, `resources/subscribe`, or\n * `resources/unsubscribe` request.\n *\n * Collision rule: when two upstreams advertise the same concrete URI, the upstream\n * appearing first in config-file order wins; the shadowed upstream's copy of that\n * resource is unreachable through the proxy until the conflict is resolved upstream.\n *\n * Template URIs (RFC 6570 forms like `file:///{path}`) are matched against incoming\n * URIs by their literal prefix (everything before the first `{`). When more than one\n * upstream advertises an overlapping template, the first-wins rule applies on a\n * prefix-equality basis.\n *\n * Concrete URI matches always take precedence over template matches, regardless of\n * config order.\n */\nexport class ResourceRouter {\n private readonly mcpOrder: string[];\n private readonly perMcp: Map<string, { resources: Resource[]; templates: ResourceTemplate[] }>;\n\n private uriOwners: Map<string, string> = new Map();\n private templateOwners: Array<{ prefix: string; template: ResourceTemplate; mcpName: string }> =\n [];\n private detectedCollisions: ResourceCollision[] = [];\n\n constructor(mcpOrder: readonly string[]) {\n this.mcpOrder = [...mcpOrder];\n this.perMcp = new Map(\n this.mcpOrder.map(name => [name, { resources: [], templates: [] }] as const),\n );\n }\n\n setResources(mcpName: string, resources: Resource[]): void {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) {\n throw new Error(`ResourceRouter: unknown mcp \"${mcpName}\"`);\n }\n entry.resources = [...resources];\n this.rebuild();\n }\n\n setTemplates(mcpName: string, templates: ResourceTemplate[]): void {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) {\n throw new Error(`ResourceRouter: unknown mcp \"${mcpName}\"`);\n }\n entry.templates = [...templates];\n this.rebuild();\n }\n\n aggregatedResources(): Resource[] {\n const result: Resource[] = [];\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry !== undefined) {\n result.push(...entry.resources);\n }\n }\n return result;\n }\n\n aggregatedTemplates(): ResourceTemplate[] {\n const result: ResourceTemplate[] = [];\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry !== undefined) {\n result.push(...entry.templates);\n }\n }\n return result;\n }\n\n /**\n * Returns the mcpName that owns the given URI, or undefined if no upstream advertises it.\n * Concrete URI matches take precedence over template prefix matches; templates are tried\n * in config-file order (first-wins).\n */\n ownerOf(uri: string): string | undefined {\n const concrete = this.uriOwners.get(uri);\n if (concrete !== undefined) {\n return concrete;\n }\n\n for (const { prefix, mcpName } of this.templateOwners) {\n if (prefix.length > 0 && uri.startsWith(prefix)) {\n return mcpName;\n }\n }\n\n return undefined;\n }\n\n collisions(): readonly ResourceCollision[] {\n return this.detectedCollisions;\n }\n\n /**\n * Returns the resources contributed by a single upstream MCP. Used by the load_mcp\n * pipeline to construct its structured response, which lists what a just-loaded MCP\n * (or an already-loaded MCP, in the idempotent no-op path) brought to the proxy.\n * Returns an empty array if the MCP has not contributed any resources (or if\n * `mcpName` is unknown).\n */\n resourcesFor(mcpName: string): readonly Resource[] {\n return this.perMcp.get(mcpName)?.resources ?? [];\n }\n\n templatesFor(mcpName: string): readonly ResourceTemplate[] {\n return this.perMcp.get(mcpName)?.templates ?? [];\n }\n\n private rebuild(): void {\n this.uriOwners = new Map();\n this.templateOwners = [];\n const collisions: ResourceCollision[] = [];\n\n for (const mcpName of this.mcpOrder) {\n const entry = this.perMcp.get(mcpName);\n if (entry === undefined) continue;\n\n for (const resource of entry.resources) {\n const existing = this.uriOwners.get(resource.uri);\n if (existing === undefined) {\n this.uriOwners.set(resource.uri, mcpName);\n } else {\n collisions.push({ uri: resource.uri, chosen: existing, shadowed: mcpName });\n }\n }\n\n for (const template of entry.templates) {\n this.templateOwners.push({\n prefix: literalPrefixOf(template.uriTemplate),\n template,\n mcpName,\n });\n }\n }\n\n this.detectedCollisions = collisions;\n }\n}\n\nfunction literalPrefixOf(uriTemplate: string): string {\n const idx = uriTemplate.indexOf(\"{\");\n return idx === -1 ? uriTemplate : uriTemplate.slice(0, idx);\n}\n","import type { UpstreamTool } from \"./upstream-client.js\";\n\nconst DISCOVER_TOOL_PREAMBLE = `Use this tool to look up the full schema of a tool before calling it with use_tool.\nCall discover_tool with a tool name from the list below to get its complete description,\ninput parameters, and output schema. Always discover a tool before using it.`;\n\nconst DYNAMIC_DISCOVERY_PREAMBLE = `Some MCP servers below are not loaded yet and are listed under <mcp_servers> with a\nshort description of what they do. To make a server's tools (and any resources or\nprompts it exposes) available, call load_mcp with its name. Once loaded, the server's\ntools will appear in the <tools> list and become callable via use_tool. Loading is\npermanent for the remainder of this session.`;\n\nconst NO_TOOLS_LOADED_FOOTER =\n \"No tools are currently loaded. Call load_mcp to make a server's tools available.\";\n\nexport class ToolCatalog {\n readonly tools: ReadonlyMap<string, UpstreamTool>;\n readonly discoverToolDescription: string;\n\n private constructor(tools: Map<string, UpstreamTool>, description: string) {\n this.tools = tools;\n this.discoverToolDescription = description;\n }\n\n static fromFlat(upstreamTools: UpstreamTool[]): ToolCatalog {\n const toolMap = new Map<string, UpstreamTool>();\n for (const tool of upstreamTools) {\n toolMap.set(tool.name, tool);\n }\n const description = buildFlatDescription(upstreamTools);\n return new ToolCatalog(toolMap, description);\n }\n\n static fromGrouped(groups: Map<string, UpstreamTool[]>): ToolCatalog {\n return ToolCatalog.fromGroupedWithLazy(groups, new Map());\n }\n\n /**\n * Same as {@link fromGrouped} but additionally accepts a map of lazy upstream MCPs\n * (those declared with a `description` field but not yet loaded). When the map is\n * non-empty, the rendered `discover_tool` description includes a `<mcp_servers>`\n * block listing them with their descriptions and an explanatory paragraph telling\n * the agent how to call `load_mcp`. When `groups` is empty, the `<tools>` block is\n * omitted in favor of a trailing sentence directing the agent to `load_mcp`.\n */\n static fromGroupedWithLazy(\n groups: Map<string, UpstreamTool[]>,\n lazyDescriptions: ReadonlyMap<string, string>,\n ): ToolCatalog {\n const toolMap = new Map<string, UpstreamTool>();\n for (const [mcpName, tools] of groups) {\n for (const tool of tools) {\n toolMap.set(`${mcpName}/${tool.name}`, tool);\n }\n }\n const description = buildGroupedDescription(groups, lazyDescriptions);\n return new ToolCatalog(toolMap, description);\n }\n\n getToolDetails(toolName: string): string {\n const tool = this.tools.get(toolName);\n\n if (tool === undefined) {\n const sortedNames = [...this.tools.keys()].sort().join(\", \");\n return `Unknown tool: \"${toolName}\". Available tools: ${sortedNames}`;\n }\n\n return buildToolDetailsString(toolName, tool);\n }\n}\n\nfunction buildFlatDescription(tools: UpstreamTool[]): string {\n const sortedTools = [...tools].sort((a, b) => a.name.localeCompare(b.name));\n const toolLines = sortedTools.map(tool => `- ${tool.name}: ${tool.description}`).join(\"\\n\");\n\n return `${DISCOVER_TOOL_PREAMBLE}\\n\\n<tools>\\n${toolLines}\\n</tools>`;\n}\n\nfunction buildGroupedDescription(\n groups: Map<string, UpstreamTool[]>,\n lazyDescriptions: ReadonlyMap<string, string>,\n): string {\n const parts: string[] = [DISCOVER_TOOL_PREAMBLE];\n\n if (lazyDescriptions.size > 0) {\n parts.push(DYNAMIC_DISCOVERY_PREAMBLE);\n parts.push(buildMcpServersBlock(lazyDescriptions));\n }\n\n if (groups.size > 0) {\n parts.push(buildToolsBlock(groups));\n } else if (lazyDescriptions.size > 0) {\n parts.push(NO_TOOLS_LOADED_FOOTER);\n } else {\n // No eager tools and no lazy MCPs — render an empty <tools> block to keep the\n // shape consistent with the non-dynamic case where the host expected a block.\n parts.push(\"<tools>\\n</tools>\");\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nfunction buildToolsBlock(groups: Map<string, UpstreamTool[]>): string {\n const sortedMcpNames = [...groups.keys()].sort();\n const sections = sortedMcpNames.map(mcpName => {\n const tools = groups.get(mcpName)!;\n const sortedTools = [...tools].sort((a, b) => a.name.localeCompare(b.name));\n // Bullets render bare tool names under the group header (per SPEC.md).\n // The namespaced form (`<mcp-name>/<tool-name>`) is what callers must pass\n // to discover_tool / use_tool — the group header on the prior line tells\n // the agent which prefix to combine with each bullet.\n const toolLines = sortedTools.map(tool => `- ${tool.name}: ${tool.description}`).join(\"\\n\");\n return `${mcpName}:\\n${toolLines}`;\n });\n\n return `<tools>\\n${sections.join(\"\\n\\n\")}\\n</tools>`;\n}\n\nfunction buildMcpServersBlock(lazyDescriptions: ReadonlyMap<string, string>): string {\n // Preserve insertion order (config-file order) rather than sorting alphabetically,\n // so the user's config layout is what the agent sees.\n const lines = [...lazyDescriptions].map(([name, desc]) => `- ${name}: ${desc}`).join(\"\\n\");\n return `<mcp_servers>\\n${lines}\\n</mcp_servers>`;\n}\n\nfunction buildToolDetailsString(displayName: string, tool: UpstreamTool): string {\n const lines: string[] = [\n `Tool: ${displayName}`,\n `Description: ${tool.description}`,\n \"\",\n \"Input Schema:\",\n JSON.stringify(tool.inputSchema, null, 2),\n ];\n\n if (tool.outputSchema !== undefined) {\n lines.push(\"\", \"Output Schema:\", JSON.stringify(tool.outputSchema, null, 2));\n }\n\n const annotationLines = buildAnnotationLines(tool);\n if (annotationLines.length > 0) {\n lines.push(\"\", \"Annotations:\", ...annotationLines);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction buildAnnotationLines(tool: UpstreamTool): string[] {\n if (tool.annotations === undefined) {\n return [];\n }\n\n const { annotations } = tool;\n const lines: string[] = [];\n\n if (annotations.title !== undefined) {\n lines.push(`- title: ${annotations.title}`);\n }\n if (annotations.readOnlyHint !== undefined) {\n lines.push(`- readOnlyHint: ${annotations.readOnlyHint}`);\n }\n if (annotations.destructiveHint !== undefined) {\n lines.push(`- destructiveHint: ${annotations.destructiveHint}`);\n }\n if (annotations.idempotentHint !== undefined) {\n lines.push(`- idempotentHint: ${annotations.idempotentHint}`);\n }\n if (annotations.openWorldHint !== undefined) {\n lines.push(`- openWorldHint: ${annotations.openWorldHint}`);\n }\n\n return lines;\n}\n","import type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n UpstreamClient,\n type UpstreamNotificationHandlers,\n type UpstreamServerRequestHandlers,\n} from \"./upstream-client.js\";\n\n/**\n * Per-upstream configuration handed to {@link UpstreamRegistry.connectAll}. The registry\n * is intentionally oblivious to what the notification and server-request handlers do —\n * the caller (typically the Orchestrator) owns that logic and supplies pre-built\n * handlers that close over its own state.\n */\nexport type UpstreamConfig = {\n transport: Transport;\n onTransportError?: (error: Error) => void;\n notifications?: UpstreamNotificationHandlers;\n serverRequests?: UpstreamServerRequestHandlers;\n};\n\n/**\n * Owns the lifecycle of every connected upstream MCP. Responsibilities are narrow:\n * spin clients up, expose them by name (or as the unique sole client in single-MCP\n * mode), and tear them all down on shutdown. Catalog building, routing, notification\n * translation, and capability aggregation are deliberately not in scope here — the\n * Orchestrator composes those concerns around this registry.\n *\n * Connection is all-or-nothing: if any client fails to connect during\n * {@link connectAll}, every already-connected client is disconnected before the\n * original error is re-thrown.\n */\nexport class UpstreamRegistry {\n private readonly clients: Map<string, UpstreamClient> = new Map();\n\n async connectAll(entries: ReadonlyArray<readonly [string, UpstreamConfig]>): Promise<void> {\n try {\n for (const [mcpName, config] of entries) {\n const client = new UpstreamClient({\n name: mcpName,\n transport: config.transport,\n onTransportError: config.onTransportError,\n notifications: config.notifications,\n serverRequests: config.serverRequests,\n });\n await client.connect();\n this.clients.set(mcpName, client);\n }\n } catch (error) {\n await this.disconnectAll();\n throw error;\n }\n }\n\n /**\n * Connects a single additional upstream. Unlike {@link connectAll}, a failure here\n * leaves any other connected clients untouched — the caller (typically the\n * Orchestrator's `loadMcp` pipeline) needs that isolation because other lazy MCPs\n * may have already been promoted to loaded, or eager MCPs are still healthy.\n *\n * Throws if `mcpName` is already in the registry; callers should check beforehand\n * (the orchestrator handles the idempotency-success case before reaching here).\n */\n async connectOne(mcpName: string, config: UpstreamConfig): Promise<UpstreamClient> {\n if (this.clients.has(mcpName)) {\n throw new Error(`UpstreamRegistry: \"${mcpName}\" is already connected`);\n }\n const client = new UpstreamClient({\n name: mcpName,\n transport: config.transport,\n onTransportError: config.onTransportError,\n notifications: config.notifications,\n serverRequests: config.serverRequests,\n });\n await client.connect();\n this.clients.set(mcpName, client);\n return client;\n }\n\n /**\n * Disconnects and removes a single upstream. Used by `loadMcp` to roll back a\n * partially-loaded MCP when a post-connect catalog query fails. No-op if the name\n * is not present.\n */\n async deleteOne(mcpName: string): Promise<void> {\n const client = this.clients.get(mcpName);\n if (client === undefined) return;\n this.clients.delete(mcpName);\n await client.disconnect();\n }\n\n get(mcpName: string): UpstreamClient | undefined {\n return this.clients.get(mcpName);\n }\n\n /**\n * Returns the sole connected client. Used by single-MCP (`--`) mode where the\n * Orchestrator guarantees there is exactly one upstream. Returns undefined when\n * zero or more than one client is connected.\n */\n sole(): UpstreamClient | undefined {\n if (this.clients.size !== 1) return undefined;\n return this.clients.values().next().value;\n }\n\n names(): readonly string[] {\n return [...this.clients.keys()];\n }\n\n entries(): IterableIterator<[string, UpstreamClient]> {\n return this.clients.entries();\n }\n\n size(): number {\n return this.clients.size;\n }\n\n async disconnectAll(): Promise<void> {\n const disconnections = [...this.clients.values()].map(client => client.disconnect());\n await Promise.all(disconnections);\n this.clients.clear();\n }\n}\n","import process from \"node:process\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n CompleteRequestSchema,\n type CompleteRequest,\n type CompleteResult,\n type CreateMessageRequest,\n type CreateMessageResult,\n type ElicitRequest,\n type ElicitResult,\n GetPromptRequestSchema,\n type GetPromptResult,\n ListPromptsRequestSchema,\n type ListPromptsResult,\n ListResourcesRequestSchema,\n type ListResourcesResult,\n ListResourceTemplatesRequestSchema,\n type ListResourceTemplatesResult,\n type ListRootsRequest,\n type ListRootsResult,\n ListToolsRequestSchema,\n type LoggingLevel,\n type LoggingMessageNotification,\n type Prompt,\n ReadResourceRequestSchema,\n type ReadResourceResult,\n type Resource,\n type ResourceTemplate,\n RootsListChangedNotificationSchema,\n type ServerCapabilities,\n SetLevelRequestSchema,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\nimport packageJson from \"../../package.json\" with { type: \"json\" };\nimport type { ToolCatalog } from \"./tool-catalog.js\";\n\nexport type ProgressEvent = {\n progress: number;\n total?: number;\n message?: string;\n};\n\n/**\n * Per-call options forwarded by the proxy server's request handlers to the orchestrator.\n *\n * - `signal`: propagates host-side cancellation through to the upstream call. When the\n * host cancels its incoming request, the SDK client emits `notifications/cancelled`\n * to the upstream.\n * - `onprogress`: invoked when the upstream emits a `notifications/progress` for the\n * in-flight call. The proxy server uses this to translate upstream progress events\n * into host-facing notifications under the host's original progress token.\n */\nexport type ProxyCallOptions = {\n signal?: AbortSignal;\n onprogress?: (progress: ProgressEvent) => void;\n};\n\nexport type ToolCaller = (\n name: string,\n input: Record<string, unknown>,\n options?: ProxyCallOptions,\n) => Promise<CallToolResult>;\n\nexport type ResourceCallbacks = {\n listResources: () => Resource[];\n listResourceTemplates: () => ResourceTemplate[];\n readResource: (uri: string, options?: ProxyCallOptions) => Promise<ReadResourceResult>;\n subscribeResource: (uri: string, options?: ProxyCallOptions) => Promise<void>;\n unsubscribeResource: (uri: string, options?: ProxyCallOptions) => Promise<void>;\n};\n\nexport type PromptCallbacks = {\n listPrompts: () => Prompt[];\n getPrompt: (\n name: string,\n args?: Record<string, string>,\n options?: ProxyCallOptions,\n ) => Promise<GetPromptResult>;\n};\n\nexport type CompletionCallback = (\n params: CompleteRequest[\"params\"],\n options?: ProxyCallOptions,\n) => Promise<CompleteResult>;\n\nexport type LoggingSetLevelCallback = (\n level: LoggingLevel,\n options?: ProxyCallOptions,\n) => Promise<void>;\n\n/**\n * Result returned by {@link LoadMcpCallback}. Kept loose (a plain JSON value) here so\n * the ProxyServer does not depend on the orchestrator's `LoadMcpResult` type — the\n * server just serializes whatever the orchestrator returns into the tool response.\n */\nexport type LoadMcpCallback = (mcpName: string) => Promise<unknown>;\n\nexport type LogMessageParams = LoggingMessageNotification[\"params\"];\n\ntype ProxyServerConfig = {\n /**\n * Function returning the current tool catalog. A function (rather than a static value)\n * lets the proxy regenerate `discover_tool`'s description on the fly when an upstream\n * emits `notifications/tools/list_changed`.\n */\n catalog: () => ToolCatalog;\n callTool: ToolCaller;\n /**\n * Aggregated capabilities to advertise to the host during `initialize`. Built by\n * `aggregateCapabilities()` from the union of all upstream capabilities. The proxy\n * always advertises `tools` regardless of upstream support.\n */\n capabilities: ServerCapabilities;\n /**\n * Resource access callbacks. Required when `capabilities.resources` is advertised;\n * otherwise the resource request handlers are not registered.\n */\n resources?: ResourceCallbacks;\n /**\n * Prompt access callbacks. Required when `capabilities.prompts` is advertised;\n * otherwise the prompt request handlers are not registered.\n */\n prompts?: PromptCallbacks;\n /**\n * Completion routing callback. Required when `capabilities.completions` is advertised;\n * otherwise the completion request handler is not registered.\n */\n complete?: CompletionCallback;\n /**\n * Logging set-level callback. Required when `capabilities.logging` is advertised;\n * otherwise the `logging/setLevel` request handler is not registered.\n */\n setLoggingLevel?: LoggingSetLevelCallback;\n /**\n * Invoked when the host emits `notifications/roots/list_changed`. The proxy will\n * call this so the orchestrator can broadcast the change to all upstreams that\n * declared the `roots` client capability to us.\n */\n onRootsListChanged?: () => void | Promise<void>;\n /**\n * Optional dynamic-discovery callback. When provided, the `load_mcp` meta-tool is\n * registered alongside `discover_tool` and `use_tool`. Absent in single-MCP mode\n * and in config-file mode with no `description` fields. See SPEC.md § \"Dynamic\n * Discovery\" and § \"Tools > load_mcp\".\n */\n loadMcp?: LoadMcpCallback;\n};\n\nconst DISCOVER_TOOL_NAME = \"discover_tool\";\nconst USE_TOOL_NAME = \"use_tool\";\nconst LOAD_MCP_NAME = \"load_mcp\";\n\nconst USE_TOOL_DESCRIPTION =\n \"Use a tool that was previously discovered with the discover_tool tool.\";\n\nconst LOAD_MCP_DESCRIPTION =\n \"Load a previously-deferred MCP server so that its tools, resources, and prompts become available. Pass the server name as shown in the <mcp_servers> block of the discover_tool description. Loading is permanent for the remainder of this session.\";\n\nconst DISCOVER_TOOL_INPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n tool_name: { type: \"string\" as const },\n },\n required: [\"tool_name\"],\n};\n\nconst USE_TOOL_INPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n tool_name: { type: \"string\" as const },\n tool_input: { type: \"object\" as const, additionalProperties: true, default: {} },\n },\n required: [\"tool_name\"],\n};\n\nconst LOAD_MCP_INPUT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n mcp_name: { type: \"string\" as const },\n },\n required: [\"mcp_name\"],\n};\n\nconst DiscoverToolArgsSchema = z.object({ tool_name: z.string() });\nconst UseToolArgsSchema = z.object({\n tool_name: z.string(),\n tool_input: z.record(z.string(), z.unknown()).default({}),\n});\nconst LoadMcpArgsSchema = z.object({ mcp_name: z.string() });\n\nexport class ProxyServer {\n private readonly catalog: () => ToolCatalog;\n private readonly callTool: ToolCaller;\n private readonly capabilities: ServerCapabilities;\n private readonly resources: ResourceCallbacks | undefined;\n private readonly prompts: PromptCallbacks | undefined;\n private readonly complete: CompletionCallback | undefined;\n private readonly setLoggingLevelCallback: LoggingSetLevelCallback | undefined;\n private readonly onRootsListChangedCallback: (() => void | Promise<void>) | undefined;\n private readonly loadMcpCallback: LoadMcpCallback | undefined;\n private sdkServer: Server | null = null;\n\n constructor({\n catalog,\n callTool,\n capabilities,\n resources,\n prompts,\n complete,\n setLoggingLevel,\n onRootsListChanged,\n loadMcp,\n }: ProxyServerConfig) {\n this.catalog = catalog;\n this.callTool = callTool;\n this.capabilities = capabilities;\n this.resources = resources;\n this.prompts = prompts;\n this.complete = complete;\n this.setLoggingLevelCallback = setLoggingLevel;\n this.onRootsListChangedCallback = onRootsListChanged;\n this.loadMcpCallback = loadMcp;\n }\n\n buildServer(): Server {\n const server = new Server(\n {\n name: \"dynamic-discovery-mcp\",\n version: packageJson.version,\n },\n {\n capabilities: this.capabilities,\n },\n );\n\n this.registerToolHandlers(server);\n if (this.capabilities.resources !== undefined && this.resources !== undefined) {\n this.registerResourceHandlers(server, this.resources);\n }\n if (this.capabilities.prompts !== undefined && this.prompts !== undefined) {\n this.registerPromptHandlers(server, this.prompts);\n }\n if (this.capabilities.completions !== undefined && this.complete !== undefined) {\n this.registerCompletionHandler(server, this.complete);\n }\n if (this.capabilities.logging !== undefined && this.setLoggingLevelCallback !== undefined) {\n this.registerLoggingHandler(server, this.setLoggingLevelCallback);\n }\n if (this.onRootsListChangedCallback !== undefined) {\n const callback = this.onRootsListChangedCallback;\n server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {\n await callback();\n });\n }\n\n this.sdkServer = server;\n return server;\n }\n\n /**\n * Forwards an upstream-initiated `sampling/createMessage` request to the host. The\n * upstream's abort signal is threaded through so cancellation by the upstream\n * propagates to the host.\n */\n async forwardCreateMessage(\n params: CreateMessageRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<CreateMessageResult> {\n const server = this.requireSdkServer();\n return server.createMessage(params, options);\n }\n\n /**\n * Forwards an upstream-initiated `elicitation/create` request to the host.\n */\n async forwardElicitInput(\n params: ElicitRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ElicitResult> {\n const server = this.requireSdkServer();\n return server.elicitInput(params, options);\n }\n\n /**\n * Forwards an upstream-initiated `roots/list` request to the host.\n */\n async forwardListRoots(\n params: ListRootsRequest[\"params\"],\n options: { signal: AbortSignal },\n ): Promise<ListRootsResult> {\n const server = this.requireSdkServer();\n return server.listRoots(params, options);\n }\n\n private requireSdkServer(): Server {\n if (this.sdkServer === null) {\n throw new Error(\"ProxyServer is not built. Call buildServer() before forwarding requests.\");\n }\n return this.sdkServer;\n }\n\n async start(): Promise<void> {\n const server = this.buildServer();\n const transport = new StdioServerTransport();\n process.stderr.write(\"Starting dynamic-discovery-mcp server over stdio\\n\");\n await server.connect(transport);\n }\n\n /**\n * Notifies the host that the discover_tool description has changed because an upstream\n * emitted `notifications/tools/list_changed`. The host should re-fetch the tools list\n * to pick up the regenerated catalog. Silently no-ops if `buildServer()` has not been\n * called yet.\n */\n async sendToolListChanged(): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendToolListChanged();\n }\n }\n\n /**\n * Notifies the host that the proxy's aggregated resource list has changed. Silently\n * no-ops if `buildServer()` has not been called yet. Errors propagate.\n */\n async sendResourceListChanged(): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendResourceListChanged();\n }\n }\n\n /**\n * Notifies the host that a specific subscribed resource has changed. Silently no-ops\n * if `buildServer()` has not been called yet.\n */\n async sendResourceUpdated(params: { uri: string }): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendResourceUpdated(params);\n }\n }\n\n /**\n * Notifies the host that the proxy's aggregated prompt list has changed. Silently\n * no-ops if `buildServer()` has not been called yet.\n */\n async sendPromptListChanged(): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendPromptListChanged();\n }\n }\n\n /**\n * Builds per-call options for a request handler. Extracts the host's\n * `progressToken` from `_meta` (if any) and wires an `onprogress` callback that\n * re-emits progress notifications back to the host under that same token. This\n * is the single seam where progress translation lives — every forward-direction\n * handler routes through here.\n */\n private buildCallOptions(\n request: { params: { _meta?: { progressToken?: string | number } } },\n extra: {\n signal: AbortSignal;\n sendNotification: (notification: {\n method: string;\n params?: Record<string, unknown>;\n }) => Promise<void>;\n },\n ): ProxyCallOptions {\n const options: ProxyCallOptions = { signal: extra.signal };\n const progressToken = request.params._meta?.progressToken;\n if (progressToken !== undefined) {\n options.onprogress = progress => {\n void extra.sendNotification({\n method: \"notifications/progress\",\n params: {\n progressToken,\n progress: progress.progress,\n total: progress.total,\n message: progress.message,\n },\n });\n };\n }\n return options;\n }\n\n private registerToolHandlers(server: Server): void {\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n type ListedTool = {\n name: string;\n description: string;\n inputSchema: { type: \"object\"; properties: Record<string, unknown>; required: string[] };\n };\n const tools: ListedTool[] = [\n {\n name: DISCOVER_TOOL_NAME,\n description: this.catalog().discoverToolDescription,\n inputSchema: DISCOVER_TOOL_INPUT_SCHEMA,\n },\n {\n name: USE_TOOL_NAME,\n description: USE_TOOL_DESCRIPTION,\n inputSchema: USE_TOOL_INPUT_SCHEMA,\n },\n ];\n if (this.loadMcpCallback !== undefined) {\n tools.push({\n name: LOAD_MCP_NAME,\n description: LOAD_MCP_DESCRIPTION,\n inputSchema: LOAD_MCP_INPUT_SCHEMA,\n });\n }\n return { tools };\n });\n\n server.setRequestHandler(\n CallToolRequestSchema,\n async (request, extra): Promise<CallToolResult> => {\n const { name, arguments: rawArgs } = request.params;\n const catalog = this.catalog();\n\n if (name === DISCOVER_TOOL_NAME) {\n const args = DiscoverToolArgsSchema.parse(rawArgs ?? {});\n return {\n content: [{ type: \"text\", text: catalog.getToolDetails(args.tool_name) }],\n };\n }\n\n if (name === USE_TOOL_NAME) {\n const args = UseToolArgsSchema.parse(rawArgs ?? {});\n if (!catalog.tools.has(args.tool_name)) {\n return {\n content: [{ type: \"text\", text: catalog.getToolDetails(args.tool_name) }],\n };\n }\n return await this.callTool(\n args.tool_name,\n args.tool_input,\n this.buildCallOptions(request, extra),\n );\n }\n\n if (name === LOAD_MCP_NAME && this.loadMcpCallback !== undefined) {\n const args = LoadMcpArgsSchema.parse(rawArgs ?? {});\n try {\n const result = await this.loadMcpCallback(args.mcp_name);\n return {\n // The structured payload is JSON-serialized into a text block. We also\n // populate `structuredContent` so MCP clients that prefer typed data can\n // consume the same response without parsing the text body.\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n structuredContent: result as Record<string, unknown>,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: message }],\n };\n }\n }\n\n return {\n isError: true,\n content: [{ type: \"text\", text: `Unknown tool: \"${name}\"` }],\n };\n },\n );\n }\n\n private registerResourceHandlers(server: Server, callbacks: ResourceCallbacks): void {\n server.setRequestHandler(\n ListResourcesRequestSchema,\n async (): Promise<ListResourcesResult> => ({\n resources: callbacks.listResources(),\n }),\n );\n\n server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async (): Promise<ListResourceTemplatesResult> => ({\n resourceTemplates: callbacks.listResourceTemplates(),\n }),\n );\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request, extra): Promise<ReadResourceResult> => {\n return callbacks.readResource(request.params.uri, this.buildCallOptions(request, extra));\n },\n );\n\n server.setRequestHandler(SubscribeRequestSchema, async (request, extra) => {\n await callbacks.subscribeResource(request.params.uri, this.buildCallOptions(request, extra));\n return {};\n });\n\n server.setRequestHandler(UnsubscribeRequestSchema, async (request, extra) => {\n await callbacks.unsubscribeResource(\n request.params.uri,\n this.buildCallOptions(request, extra),\n );\n return {};\n });\n }\n\n private registerPromptHandlers(server: Server, callbacks: PromptCallbacks): void {\n server.setRequestHandler(\n ListPromptsRequestSchema,\n async (): Promise<ListPromptsResult> => ({\n prompts: callbacks.listPrompts(),\n }),\n );\n\n server.setRequestHandler(\n GetPromptRequestSchema,\n async (request, extra): Promise<GetPromptResult> => {\n return callbacks.getPrompt(\n request.params.name,\n request.params.arguments,\n this.buildCallOptions(request, extra),\n );\n },\n );\n }\n\n private registerCompletionHandler(server: Server, callback: CompletionCallback): void {\n server.setRequestHandler(\n CompleteRequestSchema,\n async (request, extra): Promise<CompleteResult> => {\n return callback(request.params, this.buildCallOptions(request, extra));\n },\n );\n }\n\n private registerLoggingHandler(server: Server, callback: LoggingSetLevelCallback): void {\n server.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {\n await callback(request.params.level, this.buildCallOptions(request, extra));\n return {};\n });\n }\n\n /**\n * Forwards a log message from an upstream MCP to the host. Silently no-ops if\n * `buildServer()` has not been called yet.\n */\n async sendLoggingMessage(params: LogMessageParams): Promise<void> {\n if (this.sdkServer !== null) {\n await this.sdkServer.sendLoggingMessage(params);\n }\n }\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport process from \"node:process\";\nimport { detectFormat, SCHEMA_URL } from \"./format.js\";\n\nexport interface InitOptions {\n /** Explicit target file path (relative to cwd or absolute). Extension determines format. */\n path?: string;\n /** Shortcut: write `mcp.yaml` instead of `mcp.json`. Ignored if `path` is set. */\n yaml?: boolean;\n /** Overwrite an existing file. Default: false. */\n force?: boolean;\n /** Override the current working directory (for tests). */\n cwd?: string;\n /** Override the stdout writer (for tests). */\n write?: (chunk: string) => void;\n /** Override the file writer (for tests). */\n fileWriter?: (path: string, contents: string) => void;\n /** Override the existence check (for tests). */\n fileExists?: (path: string) => boolean;\n}\n\n/**\n * Implementation of `dynmcp init`. Writes a starter config file at the\n * resolved path. The written file has `$schema` set and an empty `mcp`\n * map; it is intentionally not yet runtime-valid (the Zod schema requires\n * `mcp` to be non-empty). The next `dynmcp add` makes it valid.\n */\nexport function init(options: InitOptions = {}): void {\n const cwd = options.cwd ?? process.cwd();\n const stdout = options.write ?? ((chunk: string) => void process.stdout.write(chunk));\n const fileWriter = options.fileWriter ?? ((p, c) => writeFileSync(p, c, \"utf-8\"));\n const fileExists = options.fileExists ?? (p => existsSync(p));\n\n const targetPath = resolveInitPath({ cwd, path: options.path, yaml: options.yaml === true });\n const format = detectFormat(targetPath);\n\n if (fileExists(targetPath) && options.force !== true) {\n throw new Error(`File already exists: ${targetPath}\\nUse --force to overwrite.`);\n }\n\n const contents = format === \"yaml\" ? renderYamlSkeleton() : renderJsonSkeleton();\n fileWriter(targetPath, contents);\n\n stdout(`Wrote ${targetPath}\\n`);\n stdout(\"\\nThis config has no MCPs yet. Add one with:\\n\");\n stdout(\" dynmcp add <name> --command <cmd> (stdio upstream)\\n\");\n stdout(\" dynmcp add <name> --transport streamable-http --url <url> (remote HTTP upstream)\\n\");\n stdout(\"\\nSee https://dynamicmcp.tools for full documentation.\\n\");\n}\n\nfunction resolveInitPath(opts: { cwd: string; path: string | undefined; yaml: boolean }): string {\n if (opts.path !== undefined) {\n return resolve(opts.cwd, opts.path);\n }\n return resolve(opts.cwd, opts.yaml ? \"mcp.yaml\" : \"mcp.json\");\n}\n\nfunction renderJsonSkeleton(): string {\n const body = JSON.stringify({ $schema: SCHEMA_URL, mcp: {} }, null, 2);\n return `${body}\\n`;\n}\n\nfunction renderYamlSkeleton(): string {\n return `# yaml-language-server: $schema=${SCHEMA_URL}\\n\\nmcp: {}\\n`;\n}\n","import { extname } from \"node:path\";\n\nexport type ConfigFileFormat = \"json\" | \"yaml\";\n\n/**\n * Determine the file format from its path extension. `.yml` and `.yaml`\n * are treated as YAML; everything else (including `.json` and any other\n * extension) is treated as JSON. Matches the rule used by the config\n * loader so `init`/`add` and the proxy runtime stay in lockstep.\n */\nexport function detectFormat(filePath: string): ConfigFileFormat {\n const ext = extname(filePath).toLowerCase();\n return ext === \".yml\" || ext === \".yaml\" ? \"yaml\" : \"json\";\n}\n\n/** URL of the published JSON Schema served by the docs site. */\nexport const SCHEMA_URL = \"https://dynamicmcp.tools/config.json\";\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport process from \"node:process\";\nimport { type Document, parseDocument } from \"yaml\";\nimport { resolveConfigPath } from \"../config/loader.js\";\nimport { MCP_NAME_PATTERN, transportConfigSchema } from \"../config/schema.js\";\nimport { detectFormat } from \"./format.js\";\n\nexport type TransportKind = \"stdio\" | \"streamable-http\" | \"sse\";\n\nexport interface AddOptions {\n /** Name of the MCP entry to add. Must match MCP_NAME_PATTERN. */\n name: string;\n /** Transport for the new entry. */\n transport: TransportKind;\n /** Explicit config path. Otherwise auto-discovered. */\n configPath?: string;\n /** Overwrite an existing entry with the same name. Default: false. */\n force?: boolean;\n /** Per-entry description; presence makes the entry lazy (dynamic discovery). */\n description?: string;\n\n // stdio\n command?: string;\n args?: string[];\n /** Each entry must be `KEY=VAL`. */\n envVars?: string[];\n\n // streamable-http / sse\n url?: string;\n /** Each entry must be `Name: Value`. */\n headers?: string[];\n clientId?: string;\n clientSecret?: string;\n scope?: string;\n\n /** Override the stdout writer (for tests). */\n write?: (chunk: string) => void;\n /** Override the file reader (for tests). */\n fileReader?: (path: string) => string;\n /** Override the file writer (for tests). */\n fileWriter?: (path: string, contents: string) => void;\n /** Override the config-path resolver (for tests). */\n resolvePath?: (configPath: string | undefined) => string;\n}\n\n/**\n * Implementation of `dynmcp add`. Builds an MCP entry from the provided\n * flags, validates it against the transport discriminated-union schema,\n * and writes it back into the resolved config file. Preserves YAML\n * comments via the `yaml` library's Document API. Never interpolates\n * `${VAR}` references — they round-trip verbatim.\n */\nexport function add(options: AddOptions): void {\n validateName(options.name);\n\n const stdout = options.write ?? ((chunk: string) => void process.stdout.write(chunk));\n const fileReader = options.fileReader ?? (p => readFileSync(p, \"utf-8\"));\n const fileWriter = options.fileWriter ?? ((p, c) => writeFileSync(p, c, \"utf-8\"));\n const resolvePath = options.resolvePath ?? resolveConfigPath;\n\n let targetPath: string;\n try {\n targetPath = resolvePath(options.configPath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`${message}\\nHint: run 'dynmcp init' to create a starter config file.`);\n }\n\n const raw = fileReader(targetPath);\n const format = detectFormat(targetPath);\n\n const entry = buildEntry(options);\n const parsed = transportConfigSchema.safeParse(entry);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map(i => ` - ${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid MCP entry:\\n${issues}`);\n }\n\n const next =\n format === \"yaml\"\n ? writeYaml(raw, options.name, parsed.data, options.force === true)\n : writeJson(raw, options.name, parsed.data, options.force === true);\n\n fileWriter(targetPath, next);\n stdout(`Added '${options.name}' (${options.transport}) to ${targetPath}\\n`);\n}\n\nfunction validateName(name: string): void {\n if (!MCP_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid MCP name '${name}'. Names must match ${MCP_NAME_PATTERN.source} ` +\n \"(lowercase letters, digits, and dashes; starting with a letter or digit).\",\n );\n }\n}\n\nfunction buildEntry(options: AddOptions): Record<string, unknown> {\n if (options.transport === \"stdio\") {\n if (options.command === undefined || options.command.length === 0) {\n throw new Error(\"--command is required for stdio transport\");\n }\n const entry: Record<string, unknown> = {\n transport: \"stdio\",\n command: options.command,\n };\n if (options.description !== undefined) entry.description = options.description;\n if (options.args !== undefined && options.args.length > 0) {\n entry.args = options.args;\n }\n if (options.envVars !== undefined && options.envVars.length > 0) {\n entry.env = parseKeyValuePairs(options.envVars, \"--env\");\n }\n return entry;\n }\n\n if (options.url === undefined || options.url.length === 0) {\n throw new Error(`--url is required for ${options.transport} transport`);\n }\n const entry: Record<string, unknown> = {\n transport: options.transport,\n url: options.url,\n };\n if (options.description !== undefined) entry.description = options.description;\n if (options.headers !== undefined && options.headers.length > 0) {\n entry.headers = parseHeaderPairs(options.headers);\n }\n const auth = buildAuthBlock(options);\n if (auth !== undefined) entry.auth = auth;\n return entry;\n}\n\nfunction buildAuthBlock(options: AddOptions): Record<string, string> | undefined {\n const hasAny =\n options.clientId !== undefined ||\n options.clientSecret !== undefined ||\n options.scope !== undefined;\n if (!hasAny) return undefined;\n\n if (options.clientId === undefined) {\n throw new Error(\"--client-id is required when --client-secret or --scope is provided\");\n }\n const auth: Record<string, string> = { client_id: options.clientId };\n if (options.clientSecret !== undefined) auth.client_secret = options.clientSecret;\n if (options.scope !== undefined) auth.scope = options.scope;\n return auth;\n}\n\nfunction parseKeyValuePairs(pairs: string[], flag: string): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of pairs) {\n const eq = pair.indexOf(\"=\");\n if (eq <= 0) {\n throw new Error(`${flag} expects KEY=VALUE (got: ${JSON.stringify(pair)})`);\n }\n const key = pair.slice(0, eq);\n out[key] = pair.slice(eq + 1);\n }\n return out;\n}\n\nfunction parseHeaderPairs(pairs: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of pairs) {\n const colon = pair.indexOf(\":\");\n if (colon <= 0) {\n throw new Error(`--header expects \"Name: Value\" (got: ${JSON.stringify(pair)})`);\n }\n const key = pair.slice(0, colon).trim();\n const value = pair.slice(colon + 1).trim();\n if (key.length === 0) {\n throw new Error(`--header name cannot be empty (got: ${JSON.stringify(pair)})`);\n }\n out[key] = value;\n }\n return out;\n}\n\nfunction writeJson(raw: string, name: string, entry: unknown, force: boolean): string {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse config as JSON: ${message}`);\n }\n if (!isPlainObject(parsed)) {\n throw new Error(\"Top-level config must be a JSON object.\");\n }\n let mcp = parsed.mcp;\n if (mcp === undefined) {\n mcp = {};\n parsed.mcp = mcp;\n } else if (!isPlainObject(mcp)) {\n throw new Error(\"Config field 'mcp' must be an object.\");\n }\n const mcpRecord = mcp as Record<string, unknown>;\n if (mcpRecord[name] !== undefined && !force) {\n throw new Error(`Entry '${name}' already exists. Use --force to overwrite.`);\n }\n mcpRecord[name] = entry;\n return `${JSON.stringify(parsed, null, 2)}\\n`;\n}\n\nfunction writeYaml(raw: string, name: string, entry: unknown, force: boolean): string {\n const doc: Document = parseDocument(raw);\n if (doc.errors.length > 0) {\n const first = doc.errors[0]?.message ?? \"unknown error\";\n throw new Error(`Failed to parse config as YAML: ${first}`);\n }\n if (!doc.has(\"mcp\")) {\n doc.set(\"mcp\", {});\n }\n const path: [string, string] = [\"mcp\", name];\n if (doc.hasIn(path) && !force) {\n throw new Error(`Entry '${name}' already exists. Use --force to overwrite.`);\n }\n doc.setIn(path, entry);\n return doc.toString();\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { cli } from \"./cli.js\";\nimport process from \"node:process\";\n\nasync function main() {\n cli.parse(process.argv);\n}\n\nmain();\n"],"mappings":"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","names":["import_node_process","mcpName","mcpName","mcpName","info","import_node_process","import_node_fs","import_node_path","import_node_process","process","dotenv","list","process","parseYaml","import_zod","import_node_process","resolve","process","resolve","timer","description","mcpName","process","import_node_process","resolveOAuthCapableEntry","defaultStatusWriter","mcpName","process","import_node_process","process","built","auth","import_node_process","mcpName","import_node_process","import_types","process","process","mcpName","auth","import_node_process","import_stdio","import_node_process","mcpName","mcpName","mcpName","description","mcpName","mcpName","description","mcpName","process","import_node_process","import_stdio","import_types","import_zod","process","mcpName","process","import_node_fs","import_node_path","import_node_process","import_node_path","process","import_node_fs","import_node_process","import_yaml","process","entry","auth","chalk","figlet","process","import_node_process","process"]}