diff --git a/CLAUDE.md b/CLAUDE.md index e208a86..018ad90 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,14 +8,14 @@ DesktopSetup is the Cloud Security Alliance's machine bootstrap. Scripts manage **macOS (Bash):** - `macos-work-tools.sh` — Core work apps (1Password, Slack, Zoom, Chrome, Office, Git, GitHub CLI) + optional dev profile (VS Code, AWS CLI, Wrangler). Post-install: `gh auth login` + Git identity from GitHub profile -- `macos-ai-tools.sh` — AI desktop apps (Claude Desktop, ChatGPT) + Git, GitHub CLI + auth + Git identity from GitHub profile, AI coding CLIs (Claude Code, Codex, Gemini) with migration from wrong install methods. Registers accessible CSA plugin marketplaces with Claude Code (via `gh`-probed access check) -- `macos-update.sh` — Updates everything: Homebrew formulas/casks, npm globals, pip packages, Claude Code (`claude update`), plus syncs CSA plugin marketplaces (adds missing accessible ones, refreshes all registered). Snapshots all versions before updating for rollback. -- `macos-plugins.sh` — Standalone plugin install/update. Just the plugin-related work from `macos-update.sh` (register CSA marketplaces, install default plugins, refresh marketplaces) without the Homebrew/npm/pip steps. Use when you just want to get current on plugins without the full update cycle. +- `macos-ai-tools.sh` — AI desktop apps (Claude Desktop, ChatGPT) + Git, GitHub CLI + auth + Git identity from GitHub profile, AI coding CLIs (Claude Code, Codex, Gemini) with migration from wrong install methods. Registers accessible CSA plugin marketplaces with Claude Code (via `gh`-probed access check) and the CSA MCP server (`csa-mcp`) for users with CSA-Internal access +- `macos-update.sh` — Updates everything: Homebrew formulas/casks, npm globals, pip packages, Claude Code (`claude update`), plus syncs CSA plugin marketplaces (adds missing accessible ones, refreshes all registered) and registers the CSA MCP server if missing. Snapshots all versions before updating for rollback. +- `macos-plugins.sh` — Standalone plugin install/update. Just the plugin-related work from `macos-update.sh` (register CSA marketplaces, install default plugins, refresh marketplaces, register CSA MCP server) without the Homebrew/npm/pip steps. Use when you just want to get current on plugins without the full update cycle. - `macos-mcp-setup.sh` — Configures MCP servers (Airtable, GitHub, Gmail) for Claude Code, Codex, and Gemini. Discovers tokens from existing config files and environment, validates them against each service's API, and writes to each tool's config. **Windows (PowerShell):** - `windows-work-tools.ps1` — Same tool set as macOS work tools, using winget instead of Homebrew -- `windows-ai-tools.ps1` — Same AI tools as macOS (desktop apps + CLIs), using winget + npm. Includes migration support, Git identity from GitHub profile, and CSA plugin marketplace registration. +- `windows-ai-tools.ps1` — Same AI tools as macOS (desktop apps + CLIs), using winget + npm. Includes migration support, Git identity from GitHub profile, CSA plugin marketplace registration, and CSA MCP server registration. - `windows-plugins.ps1` — Standalone plugin install/update, Windows counterpart to `macos-plugins.sh`. Runs just the plugin workflow without touching winget apps. **Cross-platform:** @@ -85,7 +85,7 @@ Requires Python 3 (the script calls `abort` if `python3` is not found). Gmail is All scripts declare `SCRIPT_VERSION="YYYY.MMDDHHSS"` near the top. Update this value when making changes — use the current date/time in that format. ### Shared boilerplate -All scripts (both platforms) duplicate their output helpers, precondition checks, and utility functions. macOS uses `has_command`, `confirm`, `ensure_brew_in_path`; Windows uses `Has-Command`. The two macOS install scripts additionally share `install_xcode_cli_tools`, `install_homebrew`, `install_node`, `setup_gh_auth`, and `setup_git_identity`. The `CSA_MARKETPLACES` array (list of plugin marketplace `ORG/REPO` strings) is duplicated across **five** scripts: `macos-ai-tools.sh`, `windows-ai-tools.ps1`, `macos-update.sh`, `macos-plugins.sh`, `windows-plugins.ps1` — update all five when adding a new marketplace, and bump each file's `SCRIPT_VERSION`. **When changing shared logic, update all files that use it.** The marketplace-name → repo mapping is similarly duplicated across all five scripts: as a `plugin_marketplace_repo` bash function in the three `.sh` files (function-based because macOS ships bash 3.2, which doesn't support `declare -A` associative arrays), and as a `$PluginMarketplaceRepos` hashtable in the two `.ps1` files. The actual plugin lists, however, are single-source: `scripts/csa-plugins.txt` and `scripts/csa-plugins-internal.txt` are fetched from HEAD at runtime, so list-only changes do **not** require a script edit or `SCRIPT_VERSION` bump. +All scripts (both platforms) duplicate their output helpers, precondition checks, and utility functions. macOS uses `has_command`, `confirm`, `ensure_brew_in_path`; Windows uses `Has-Command`. The two macOS install scripts additionally share `install_xcode_cli_tools`, `install_homebrew`, `install_node`, `setup_gh_auth`, and `setup_git_identity`. The `CSA_MARKETPLACES` array (list of plugin marketplace `ORG/REPO` strings) is duplicated across **five** scripts: `macos-ai-tools.sh`, `windows-ai-tools.ps1`, `macos-update.sh`, `macos-plugins.sh`, `windows-plugins.ps1` — update all five when adding a new marketplace, and bump each file's `SCRIPT_VERSION`. **When changing shared logic, update all files that use it.** The marketplace-name → repo mapping is similarly duplicated across all five scripts: as a `plugin_marketplace_repo` bash function in the three `.sh` files (function-based because macOS ships bash 3.2, which doesn't support `declare -A` associative arrays), and as a `$PluginMarketplaceRepos` hashtable in the two `.ps1` files. The same five files also share the CSA MCP server registration logic (`setup_csa_mcp_server` / `Register-CSAMcpServer`) and the constants `CSA_MCP_NAME`, `CSA_MCP_URL`, `CSA_MCP_GATE_REPO` — keep these in sync too. The actual plugin lists, however, are single-source: `scripts/csa-plugins.txt` and `scripts/csa-plugins-internal.txt` are fetched from HEAD at runtime, so list-only changes do **not** require a script edit or `SCRIPT_VERSION` bump. ### Plugin marketplace registration `macos-ai-tools.sh`, `windows-ai-tools.ps1`, `macos-update.sh`, `macos-plugins.sh`, and `windows-plugins.ps1` share the same silent-by-default registration contract: @@ -105,6 +105,15 @@ The plugin-install contract is shared across all five scripts — `macos-ai-tool 7. Preflight preview: each script's plan-display phase also calls `install_plugins_preview` / `Show-PluginsPreview`, which fetches the list files and compares against `claude plugin list` to print a one-liner like `Plugins install up to 2 new (38 already present)`. No `gh`-probes, so the count is an upper bound — CSA plugins the user can't access get filtered at actual install time. 8. List-only changes (adding or removing a plugin from either `.txt` file) require a single commit to `main` and propagate to existing users on their next installer or `macos-update.sh` run — no script edit or `SCRIPT_VERSION` bump. +### CSA MCP server registration +`macos-ai-tools.sh`, `windows-ai-tools.ps1`, `macos-update.sh`, `macos-plugins.sh`, and `windows-plugins.ps1` register the CSA MCP server (`csa-mcp` → `https://cloudsecurityalliance.org/mcp`, HTTP transport, OAuth 2.1 + PKCE) with Claude Code. The server is in soft launch — open to `@cloudsecurityalliance.org` accounts and beta testers — so registration is silent-by-default and gated behind a `gh`-probe of `CloudSecurityAlliance-Internal/CSA-Plugins` (a CSA-membership proxy that mirrors the plugin-marketplace contract): +1. If `claude` or `gh` is missing, or `gh` is unauthenticated, return silently — no chatter for users without a CSA-Internal-eligible GitHub account. +2. If `csa-mcp` is already registered (parsed from `claude mcp list`, matching `^csa-mcp[: ]`), return silently. Re-running `claude mcp add` for an existing entry would either error or — if it succeeded — invalidate the user's authenticated OAuth session, so we never clobber. +3. Otherwise, `gh api repos/CloudSecurityAlliance-Internal/CSA-Plugins` is called as the gate. Non-zero exit → silent skip. Zero exit → run `claude mcp add --transport http --scope user csa-mcp https://cloudsecurityalliance.org/mcp`. +4. **Output is silent unless registration actually happened.** On success, print a `Registered Claude Code MCP server: csa-mcp` line followed by `Run /mcp inside Claude Code to authenticate with the CSA MCP server.` (the OAuth flow is browser-driven and must be initiated by the user). On `add` failure, print a warn line with the captured stderr indented underneath, matching the marketplace-add error format. +5. Currently Claude Code only. Codex and Gemini support OAuth-HTTP MCP transports too but their config formats differ; adding them is future work. +6. **The CSA MCP server is *not* a token-discovery target for `macos-mcp-setup.sh`.** That script's pipeline is built around static bearer tokens (Airtable, GitHub, Gmail) — it discovers, validates, and writes them to each CLI's config. OAuth flows have no token to pre-discover, so `csa-mcp` belongs in the install/update scripts, not in `macos-mcp-setup.sh`. + ### Script execution flow All macOS scripts follow the same pattern: `main` → preconditions → preflight (show plan) → confirm → action steps → summary. `macos-ai-tools.sh` adds a migration layer: `detect_migrations()` runs during preflight, then `migrate_*()` runs before each tool's install to remove wrong-method installs. `macos-update.sh` takes a pre-update snapshot (to `~/Library/Logs/CSA-DesktopSetup/`) before showing the plan, enabling version rollback if updates break something. diff --git a/scripts/macos-ai-tools.sh b/scripts/macos-ai-tools.sh index f826c1b..8553404 100755 --- a/scripts/macos-ai-tools.sh +++ b/scripts/macos-ai-tools.sh @@ -23,7 +23,7 @@ set -euo pipefail -SCRIPT_VERSION="2026.04250000" +SCRIPT_VERSION="2026.04271200" # ── CSA plugin marketplaces ───────────────────────────────────────── # Plugin marketplaces to register with Claude Code. Each entry is an @@ -79,6 +79,22 @@ plugin_marketplace_repo() { esac } +# ── CSA MCP server ────────────────────────────────────────────────── +# Registers the CSA MCP server with Claude Code (HTTP transport, +# OAuth 2.1 + PKCE). The server is in soft launch — open to +# @cloudsecurityalliance.org accounts and beta testers — so we gate +# registration behind a `gh`-probe of a canonical CSA-Internal repo, +# matching the silent-by-default contract used for plugin marketplaces. +# +# KEEP IN SYNC: same constants and logic in +# scripts/windows-ai-tools.ps1 +# scripts/macos-update.sh +# scripts/macos-plugins.sh +# scripts/windows-plugins.ps1 +CSA_MCP_NAME="csa-mcp" +CSA_MCP_URL="https://cloudsecurityalliance.org/mcp" +CSA_MCP_GATE_REPO="CloudSecurityAlliance-Internal/CSA-Plugins" + # ── Output helpers ────────────────────────────────────────────────── if [[ -t 1 ]]; then @@ -360,6 +376,7 @@ preflight() { # Plugin marketplaces echo " Plugin marketplaces probe ${#CSA_MARKETPLACES[@]} CSA repos, add any your GitHub account can access" install_plugins_preview + echo " CSA MCP server register $CSA_MCP_NAME if your GitHub account has CSA-Internal access" echo "" } @@ -799,6 +816,35 @@ setup_plugin_marketplaces() { fi } +# Register the CSA MCP server (csa-mcp) with Claude Code if missing. +# Silent-by-default: returns silently when claude/gh is unavailable, gh +# is unauthenticated, csa-mcp is already registered, or the user lacks +# CSA-Internal access. The server uses OAuth 2.1 + PKCE, so the user +# must run /mcp inside Claude Code to complete the browser sign-in — +# we print that reminder only on a fresh registration. +setup_csa_mcp_server() { + has_command claude || return 0 + has_command gh || return 0 + gh auth status >/dev/null 2>&1 || return 0 + + # Already registered? Don't clobber — would invalidate the OAuth session. + if claude mcp list 2>/dev/null | grep -qE "^${CSA_MCP_NAME}[: ]"; then + return 0 + fi + + # CSA-membership gate via gh probe of a canonical CSA-Internal repo. + gh api "repos/$CSA_MCP_GATE_REPO" >/dev/null 2>&1 || return 0 + + local add_err + if add_err="$(claude mcp add --transport http --scope user "$CSA_MCP_NAME" "$CSA_MCP_URL" 2>&1 >/dev/null)"; then + success "Registered Claude Code MCP server: $CSA_MCP_NAME" + info "Run /mcp inside Claude Code to authenticate with the CSA MCP server." + else + warn "Failed to register Claude Code MCP server '$CSA_MCP_NAME':" + printf ' %s\n' "${add_err:-}" + fi +} + # ── Plugin install ────────────────────────────────────────────────── # Fetch the public and internal plugin list files from HEAD, register # any missing marketplaces (CSA marketplaces are gh-probed first), @@ -1111,6 +1157,7 @@ main() { setup_claude_env setup_plugin_marketplaces install_plugins + setup_csa_mcp_server summary } diff --git a/scripts/macos-plugins.sh b/scripts/macos-plugins.sh index 9f0e1d8..8cc51d3 100644 --- a/scripts/macos-plugins.sh +++ b/scripts/macos-plugins.sh @@ -17,7 +17,7 @@ set -euo pipefail -SCRIPT_VERSION="2026.04250100" +SCRIPT_VERSION="2026.04271200" # ── CSA plugin marketplaces ───────────────────────────────────────── # Registered in sync_plugin_marketplaces() regardless of whether @@ -67,6 +67,13 @@ plugin_marketplace_repo() { esac } +# ── CSA MCP server ────────────────────────────────────────────────── +# See scripts/macos-ai-tools.sh for full rationale. Keep these constants +# and the setup_csa_mcp_server function in sync across all five scripts. +CSA_MCP_NAME="csa-mcp" +CSA_MCP_URL="https://cloudsecurityalliance.org/mcp" +CSA_MCP_GATE_REPO="CloudSecurityAlliance-Internal/CSA-Plugins" + # ── Output helpers ────────────────────────────────────────────────── if [[ -t 1 ]]; then @@ -327,6 +334,31 @@ sync_plugin_marketplaces() { fi } +# Register the CSA MCP server (csa-mcp) with Claude Code if missing. +# See scripts/macos-ai-tools.sh setup_csa_mcp_server for full rationale — +# silent unless we actually register, gh-probed CSA-Internal access gate, +# does not clobber existing OAuth sessions. +setup_csa_mcp_server() { + has_command claude || return 0 + has_command gh || return 0 + gh auth status >/dev/null 2>&1 || return 0 + + if claude mcp list 2>/dev/null | grep -qE "^${CSA_MCP_NAME}[: ]"; then + return 0 + fi + + gh api "repos/$CSA_MCP_GATE_REPO" >/dev/null 2>&1 || return 0 + + local add_err + if add_err="$(claude mcp add --transport http --scope user "$CSA_MCP_NAME" "$CSA_MCP_URL" 2>&1 >/dev/null)"; then + success "Registered Claude Code MCP server: $CSA_MCP_NAME" + info "Run /mcp inside Claude Code to authenticate with the CSA MCP server." + else + warn "Failed to register Claude Code MCP server '$CSA_MCP_NAME':" + printf ' %s\n' "${add_err:-}" + fi +} + # ── Preflight ─────────────────────────────────────────────────────── preflight() { @@ -337,6 +369,7 @@ preflight() { if has_command claude; then echo " Plugin marketplaces: refresh registered, add accessible CSA repos" install_plugins_preview + echo " CSA MCP server : register $CSA_MCP_NAME if your GitHub account has CSA-Internal access" else warn "claude CLI not found — install it first via scripts/macos-ai-tools.sh" abort "Nothing to do without claude CLI." @@ -358,6 +391,7 @@ main() { sync_plugin_marketplaces install_plugins + setup_csa_mcp_server info "Refreshing plugin marketplaces" claude plugin marketplace update || warn "marketplace update failed; continuing" diff --git a/scripts/macos-update.sh b/scripts/macos-update.sh index 8c022e4..94206c5 100644 --- a/scripts/macos-update.sh +++ b/scripts/macos-update.sh @@ -17,7 +17,7 @@ set -euo pipefail -SCRIPT_VERSION="2026.04242300" +SCRIPT_VERSION="2026.04271200" # ── CSA plugin marketplaces ───────────────────────────────────────── # Each update run will add any entries from this list that aren't yet @@ -66,6 +66,13 @@ plugin_marketplace_repo() { esac } +# ── CSA MCP server ────────────────────────────────────────────────── +# See scripts/macos-ai-tools.sh for full rationale. Keep these constants +# and the setup_csa_mcp_server function in sync across all five scripts. +CSA_MCP_NAME="csa-mcp" +CSA_MCP_URL="https://cloudsecurityalliance.org/mcp" +CSA_MCP_GATE_REPO="CloudSecurityAlliance-Internal/CSA-Plugins" + # ── Output helpers ────────────────────────────────────────────────── if [[ -t 1 ]]; then @@ -281,6 +288,7 @@ preflight() { if has_command claude; then echo " Plugin marketplaces: refresh registered, add accessible CSA repos" install_plugins_preview + echo " CSA MCP server : register $CSA_MCP_NAME if your GitHub account has CSA-Internal access" echo "" fi } @@ -394,6 +402,31 @@ sync_plugin_marketplaces() { claude plugin marketplace update || warn "marketplace update failed; continuing" } +# Register the CSA MCP server (csa-mcp) with Claude Code if missing. +# See scripts/macos-ai-tools.sh setup_csa_mcp_server for full rationale — +# silent unless we actually register, gh-probed CSA-Internal access gate, +# does not clobber existing OAuth sessions. +setup_csa_mcp_server() { + has_command claude || return 0 + has_command gh || return 0 + gh auth status >/dev/null 2>&1 || return 0 + + if claude mcp list 2>/dev/null | grep -qE "^${CSA_MCP_NAME}[: ]"; then + return 0 + fi + + gh api "repos/$CSA_MCP_GATE_REPO" >/dev/null 2>&1 || return 0 + + local add_err + if add_err="$(claude mcp add --transport http --scope user "$CSA_MCP_NAME" "$CSA_MCP_URL" 2>&1 >/dev/null)"; then + success "Registered Claude Code MCP server: $CSA_MCP_NAME" + info "Run /mcp inside Claude Code to authenticate with the CSA MCP server." + else + warn "Failed to register Claude Code MCP server '$CSA_MCP_NAME':" + printf ' %s\n' "${add_err:-}" + fi +} + # ── Plugin install ────────────────────────────────────────────────── # Fetch the public and internal plugin list files from HEAD, register # any missing marketplaces (CSA marketplaces are gh-probed first), @@ -657,6 +690,7 @@ main() { update_claude_code sync_plugin_marketplaces install_plugins + setup_csa_mcp_server summary } diff --git a/scripts/windows-ai-tools.ps1 b/scripts/windows-ai-tools.ps1 index e29f676..6cd08ec 100644 --- a/scripts/windows-ai-tools.ps1 +++ b/scripts/windows-ai-tools.ps1 @@ -18,7 +18,7 @@ $ErrorActionPreference = 'Stop' -$ScriptVersion = "2026.04250000" +$ScriptVersion = "2026.04271200" # ── CSA plugin marketplaces ───────────────────────────────────────── # Plugin marketplaces to register with Claude Code. Each entry is an @@ -63,6 +63,21 @@ $PluginMarketplaceRepos = @{ 'csa-plugins-official' = 'CloudSecurityAlliance/csa-plugins-official' } +# ── CSA MCP server ────────────────────────────────────────────────── +# Registers the CSA MCP server with Claude Code (HTTP transport, +# OAuth 2.1 + PKCE). Gated on `gh` access to a canonical CSA-Internal +# repo since the server is in soft launch. See +# scripts/macos-ai-tools.sh for full rationale. +# +# KEEP IN SYNC: same constants and logic in +# scripts/macos-ai-tools.sh +# scripts/macos-update.sh +# scripts/macos-plugins.sh +# scripts/windows-plugins.ps1 +$CSA_MCP_NAME = 'csa-mcp' +$CSA_MCP_URL = 'https://cloudsecurityalliance.org/mcp' +$CSA_MCP_GATE_REPO = 'CloudSecurityAlliance-Internal/CSA-Plugins' + # ── Output helpers ────────────────────────────────────────────────── function Write-Info { param([string]$Message) Write-Host "==> $Message" -ForegroundColor Cyan } @@ -410,6 +425,7 @@ function Show-Preflight { # Plugin marketplaces Write-Host " Plugin marketplaces probe $($CSA_MARKETPLACES.Count) CSA repos, add any your GitHub account can access" Show-PluginsPreview + Write-Host " CSA MCP server register $CSA_MCP_NAME if your GitHub account has CSA-Internal access" Write-Host "" } @@ -893,6 +909,36 @@ function Setup-PluginMarketplaces { } } +# Register the CSA MCP server (csa-mcp) with Claude Code if missing. +# Silent unless we actually register. Does not clobber an existing +# entry -- removing and re-adding would invalidate the OAuth session. +# The user must run /mcp inside Claude Code to complete browser sign-in; +# we print that reminder only on a fresh registration. +function Register-CSAMcpServer { + if (-not (Has-Command claude)) { return } + if (-not (Has-Command gh)) { return } + if ((Invoke-NativeQuiet { gh auth status }) -ne 0) { return } + + # Already registered? Silent skip. + $listing = claude mcp list 2>$null + foreach ($line in $listing) { + if ($line -match "^${CSA_MCP_NAME}[: ]") { return } + } + + # CSA-membership gate via gh probe of a canonical CSA-Internal repo. + if ((Invoke-NativeQuiet { gh api "repos/$CSA_MCP_GATE_REPO" }) -ne 0) { return } + + $result = Invoke-NativeCapture { claude mcp add --transport http --scope user $CSA_MCP_NAME $CSA_MCP_URL } + if ($result.ExitCode -eq 0) { + Write-Success "Registered Claude Code MCP server: $CSA_MCP_NAME" + Write-Info "Run /mcp inside Claude Code to authenticate with the CSA MCP server." + } else { + Write-Warn "Failed to register Claude Code MCP server '$CSA_MCP_NAME':" + $msg = if ($result.Output) { $result.Output } else { '' } + Write-Host " $msg" + } +} + # ── Plugin install ────────────────────────────────────────────────── # Fetch the public and internal plugin list files from HEAD, register # any missing marketplaces (CSA ones are gh-probed first), then @@ -1216,6 +1262,7 @@ function Main { Setup-ClaudeEnv Setup-PluginMarketplaces Install-Plugins + Register-CSAMcpServer Show-Summary } diff --git a/scripts/windows-plugins.ps1 b/scripts/windows-plugins.ps1 index 4af78b9..1a9921e 100644 --- a/scripts/windows-plugins.ps1 +++ b/scripts/windows-plugins.ps1 @@ -13,7 +13,7 @@ $ErrorActionPreference = 'Stop' -$ScriptVersion = "2026.04250100" +$ScriptVersion = "2026.04271200" # ── CSA plugin marketplaces ───────────────────────────────────────── # Registered in Setup-PluginMarketplaces regardless of whether @@ -57,6 +57,13 @@ $PluginMarketplaceRepos = @{ 'csa-plugins-official' = 'CloudSecurityAlliance/csa-plugins-official' } +# ── CSA MCP server ────────────────────────────────────────────────── +# See scripts/macos-ai-tools.sh for full rationale. Keep these constants +# and the Register-CSAMcpServer function in sync across all five scripts. +$CSA_MCP_NAME = 'csa-mcp' +$CSA_MCP_URL = 'https://cloudsecurityalliance.org/mcp' +$CSA_MCP_GATE_REPO = 'CloudSecurityAlliance-Internal/CSA-Plugins' + # ── Output helpers ────────────────────────────────────────────────── function Write-Info { param([string]$Message) Write-Host "==> $Message" -ForegroundColor Cyan } @@ -370,6 +377,33 @@ function Setup-PluginMarketplaces { } } +# Register the CSA MCP server (csa-mcp) with Claude Code if missing. +# See scripts/windows-ai-tools.ps1 Register-CSAMcpServer for full rationale -- +# silent unless we actually register, gh-probed CSA-Internal access gate, +# does not clobber existing OAuth sessions. +function Register-CSAMcpServer { + if (-not (Has-Command claude)) { return } + if (-not (Has-Command gh)) { return } + if ((Invoke-NativeQuiet { gh auth status }) -ne 0) { return } + + $listing = claude mcp list 2>$null + foreach ($line in $listing) { + if ($line -match "^${CSA_MCP_NAME}[: ]") { return } + } + + if ((Invoke-NativeQuiet { gh api "repos/$CSA_MCP_GATE_REPO" }) -ne 0) { return } + + $result = Invoke-NativeCapture { claude mcp add --transport http --scope user $CSA_MCP_NAME $CSA_MCP_URL } + if ($result.ExitCode -eq 0) { + Write-Success "Registered Claude Code MCP server: $CSA_MCP_NAME" + Write-Info "Run /mcp inside Claude Code to authenticate with the CSA MCP server." + } else { + Write-Warn "Failed to register Claude Code MCP server '$CSA_MCP_NAME':" + $msg = if ($result.Output) { $result.Output } else { '' } + Write-Host " $msg" + } +} + # ── Preflight ─────────────────────────────────────────────────────── function Show-Preflight { @@ -379,6 +413,7 @@ function Show-Preflight { Write-Host " Plugin marketplaces: refresh registered, add accessible CSA repos" Show-PluginsPreview + Write-Host " CSA MCP server : register $CSA_MCP_NAME if your GitHub account has CSA-Internal access" Write-Host "" } @@ -399,6 +434,7 @@ function Main { Setup-PluginMarketplaces Install-Plugins + Register-CSAMcpServer Write-Info "Refreshing plugin marketplaces" $result = Invoke-NativeCapture { claude plugin marketplace update }