import { detectClients, type McpConfigSelection } from './mcp-client-registry.js'; import { resolveKnownNetworkConfigName } from './config.js'; export interface McpSetupCliOptions { /** Refresh every detected client regardless of current registration state. */ force?: boolean; /** Emit the canonical JSON block to stdout; do not detect clients or write. */ printOnly?: boolean; /** * Auto-confirm per-client registrations (default false). In TTY * mode without `--yes`, the action prompts per detected client * before writing. In non-TTY mode (CI, piped input, no controlling * terminal) the prompt is skipped — non-interactive environments * auto-confirm so scripts don't hang. Pass `--yes` explicitly in * scripts for the safer posture. */ yes?: boolean; /** Override daemon API port (default 9200). Mirrors openclaw-setup. */ port?: string; /** Override agent name (used only on first init). Mirrors openclaw-setup. */ name?: string; /** Skip daemon start (configure only). Mirrors openclaw-setup. */ start?: boolean; /** Skip wallet funding via testnet faucet. Mirrors openclaw-setup. */ fund?: boolean; /** * Network overlay to set up on (mainnet-gnosis | mainnet-base | testnet). * Persisted as config.networkConfig; a fresh node defaults to * mainnet-gnosis. Mirrors `dkg init --network`. */ network?: string; /** Skip post-setup verification probe. Mirrors openclaw-setup. */ verify?: boolean; /** Preview without writing or starting anything. Mirrors openclaw-setup. */ dryRun?: boolean; /** * Force installed-mode command form even when invoked from inside * a monorepo dev checkout. Escape hatch for contributors who want * to test the published-CLI shape from a dev cwd. Mutually * exclusive with `--monorepo`. */ installed?: boolean; /** * Force monorepo-mode command form (writes the absolute path to * the local CLI dist). Errors if no monorepo root can be located. * Mutually exclusive with `--installed`. */ monorepo?: boolean; } /** * Setup context — drives `canonicalEntry`'s output shape. `'installed'` * is the default for npm-installed CLIs (writes * `{ command: "dkg", args: ["mcp", "serve"] }`); `'monorepo'` is the * contributor-from-dev-checkout case (writes * `{ command: "node", args: ["/packages/cli/dist/cli.js", * "mcp", "serve"] }` so the contributor's local-build runs, not a * stale globally-installed version). */ export type SetupContext = 'installed' | 'monorepo'; /** * F31: per-client registration plan item. Lifted to module scope so * the `confirmPlan` helper can take and return arrays of these * without re-declaring the shape inside the action body. `Action` * mirrors the local enum the planning loop produces. */ export type PlannedAction = 'register' | 'refresh' | 'skip'; export interface PlannedItem { s: ClientState; action: PlannedAction; } /** * Dependency surface for `mcpSetupAction`. All bundled-flow primitives * are injected so the action can be unit-tested without touching the * real filesystem or spawning the daemon. The CLI wiring in `cli.ts` * dynamically imports `@origintrail-official/dkg-adapter-openclaw` and * passes its real implementations. */ export interface McpSetupActionDeps { /** Client discovery can be supplied by an isolated setup environment. */ detectClients?: typeof detectClients; loadNetworkConfig: typeof import('@origintrail-official/dkg-adapter-openclaw').loadNetworkConfig; /** Canonical persisted-config network resolver, injectable for tests. */ resolveKnownNetworkConfigName: typeof resolveKnownNetworkConfigName; /** * Codex Round-23 Fix 30: agent-agnostic config-write helper from * `dkg-core`. Pre-fix this dep was `adapter-openclaw`'s * `writeDkgConfig` wrapper, which ran 3 OpenClaw-specific * mutations (`migrateLegacyOpenClawTransport`, plus * `delete existing.openclawAdapter` / `delete existing.openclawChannel`) * before delegating to this same `ensureDkgNodeConfig`. Those * mutations are no-ops on MCP-only configs but the dependency * was architecturally wrong — MCP setup shouldn't reach into * the OpenClaw adapter for config writes. Calling the agent- * agnostic helper directly drops the dead OpenClaw baggage from * the MCP-only setup path. The OpenClaw migrations stay scoped * to `dkg openclaw setup`'s own `writeDkgConfig` call site. */ ensureDkgNodeConfig: typeof import('@origintrail-official/dkg-core').ensureDkgNodeConfig; startDaemon: typeof import('@origintrail-official/dkg-adapter-openclaw').startDaemon; /** * Eagerly creates the node's operational wallets (generate-if-absent) * before the daemon starts, so faucet funding (testnet) and manual mainnet * funding have wallets to target even if the daemon never fully boots. * Idempotent. From `@origintrail-official/dkg-agent`; injectable for tests. */ loadOpWallets: typeof import('@origintrail-official/dkg-agent').loadOpWallets; /** * Shared best-effort faucet orchestrator — the SAME one openclaw/hermes use. * Reads `wallets.json` (with retry when the daemon was started this run), * gates on `network.faucet.url`, calls the faucet, and logs manual curl * instructions on failure. Non-throwing. From `@origintrail-official/dkg-core`. */ fundWalletsBestEffort: typeof import('@origintrail-official/dkg-core').fundWalletsBestEffort; /** * Walks ancestors looking for a DKG monorepo root. Defaulted to the * dkg-core implementation in production; injectable so tests can * stub it without touching the real filesystem. */ findDkgMonorepoRoot: typeof import('@origintrail-official/dkg-core').findDkgMonorepoRoot; /** * Codex Round-2 Bug A: resolve the DKG home directory used by the * config / daemon / faucet steps below. Defaults to the dkg-core * implementation in production; injectable so tests can pin a * deterministic home without depending on `homedir()` or env. When * mcp-setup detects monorepo context it forwards the signal here * so the bootstrap state lands in the same `~/.dkg-dev` that the * registered local CLI dist will read at MCP-client startup time. */ resolveDkgConfigHome: typeof import('@origintrail-official/dkg-core').resolveDkgConfigHome; /** * F31: per-client interactive confirm hook. Defaulted to the * production readline-based implementation. Injectable so tests * can stub deterministic answer streams without managing a real * TTY. The helper takes the `planned` array and returns a * possibly-modified copy where declined items are downgraded to * `'skip'`. * * Optional — `mcpSetupAction` falls back to the module-level * `confirmPlan` when not supplied so existing call sites keep * working unchanged. */ confirmPlan?: (planned: readonly PlannedItem[], opts: { yes: boolean; }) => Promise; } /** * F31 production-side per-client confirm prompt. Reads each * to-be-written client name from the planned array and asks the * operator interactively before writing. Skipped entries pass * through unchanged (we don't prompt about no-ops). * * Auto-confirm conditions (skip prompts entirely): * - `opts.yes === true` (operator passed `--yes`). * - `process.stdin.isTTY === false` OR `process.stdout.isTTY === false`. * Codex Round-4 Fix 5 tightened the TTY guard: the pre-fix * stdin-only check would block on an invisible readline prompt * when stdout was redirected/captured but stdin still happened * to be a TTY (e.g. `dkg mcp setup > log.txt` from an * interactive shell). Both must be a TTY for prompting; any * non-TTY end auto-confirms. * - Zero non-skip entries in the plan (nothing to confirm). * * Default empty answer (operator just hits Enter) accepts the * registration — the prompt prefix is `[Y/n]` so the lower-case * default is "yes". Only `n` / `no` (case-insensitive) declines. * * Exported so `cli.ts` can pass it through to `mcpSetupAction`'s * deps surface in production. Tests inject their own stub. */ export declare function confirmPlan(planned: readonly PlannedItem[], opts: { yes: boolean; }): Promise; type RegistrationState = 'registered' | 'stale' | 'not-registered'; interface ClientState { target: McpConfigSelection; state: RegistrationState; } /** * Main entrypoint invoked by the `dkg mcp setup` commander handler in * `cli.ts`. Idempotent — re-running on a fully-set-up tree prints * step-by-step skip notices and exits cleanly without touching any * file or restarting the daemon. */ export declare function mcpSetupAction(opts: McpSetupCliOptions, deps: McpSetupActionDeps): Promise; export {}; //# sourceMappingURL=mcp-setup.d.ts.map