using ClaudeDo.Installer.Core; namespace ClaudeDo.Installer.Steps; public sealed class RegisterMcpStep : IInstallStep { private const string ServerName = "claudedo"; private readonly Func _loadWorkerConfig; public RegisterMcpStep(Func? loadWorkerConfig = null) { _loadWorkerConfig = loadWorkerConfig ?? InstallerWorkerConfig.Load; } public string Name => "Register MCP with Claude"; // Resolves the URL from the persisted worker.config.json rather than ctx.ExternalMcpPort: // an Update run never repopulates ctx from the existing installation, so ctx would still // hold the wizard default (47822) even when the installed config has a different port. // Returns null when the port is 0 — WorkerConfig treats that as "external listener off", // so registering a URL against it would just point Claude at nothing. public static string? ResolveUrl(InstallerWorkerConfig cfg) => cfg.ExternalMcpPort == 0 ? null : $"http://127.0.0.1:{cfg.ExternalMcpPort}/mcp"; public async Task ExecuteAsync(InstallContext ctx, IProgress progress, CancellationToken ct) { if (!ctx.RegisterMcpWithClaude) { progress.Report("Skipped (not selected)"); return StepResult.Ok(); } var url = ResolveUrl(_loadWorkerConfig()); if (url is null) { progress.Report("Skipped (external_mcp_port is 0 — the external MCP listener is disabled)."); return StepResult.Ok(); } // Drop any prior registration first so a re-run (e.g. update, changed port) // overwrites cleanly instead of erroring on a duplicate name. progress.Report($"Removing existing '{ServerName}' MCP registration (if any)..."); await ProcessRunner.RunAsync(ctx.ClaudeBin, $"mcp remove --scope user {ServerName}", null, progress, ct); progress.Report($"Registering '{ServerName}' MCP server at {url}..."); var (exit, output) = await ProcessRunner.RunAsync( ctx.ClaudeBin, $"mcp add --transport http --scope user {ServerName} {url}", null, progress, ct); // Non-fatal: a missing/old Claude CLI must never block the install. Surface the // manual command so the user can register it themselves later. if (exit != 0) { progress.Report( $"Could not register MCP automatically (claude exited {exit}). " + $"Run manually: claude mcp add --transport http --scope user {ServerName} {url}"); } else { progress.Report("MCP server registered with Claude."); } return StepResult.Ok(); } }