# Barry MCP — Einrichtung in einem Befehl, auf Windows. # # irm https://mcp.barry.build/install.ps1 | iex # # ⛔ Der Zwilling von install.sh, und er verhindert dieselben Fehler -- nur # heissen sie hier anders: # # - das Programm lag in %TEMP% und war nach dem Aufraeumen weg # - es war nicht im PATH, und Claude Code meldete «command not found» # - Windows haelt Heruntergeladenes fuer nicht vertrauenswuerdig # (Zone.Identifier / SmartScreen) -- unter macOS ist das die Quarantaene # - der Geltungsbereich war das Projekt statt der Benutzer # - der Neustart wurde vergessen # # ⚠️ KEIN Administrator. Alles liegt unter dem Benutzerprofil, und der PATH # wird im Benutzerbereich gesetzt -- ein Installationsweg, der Adminrechte # verlangt, ist einer, den ein Kunde in einer verwalteten Firma nicht gehen # kann. $ErrorActionPreference = 'Stop' $basis = if ($env:BARRY_MCP_BASIS) { $env:BARRY_MCP_BASIS } else { 'https://mcp.barry.build' } $ziel = if ($env:BARRY_MCP_ZIEL) { $env:BARRY_MCP_ZIEL } else { "$env:LOCALAPPDATA\Programs\barry" } function Sagen($t) { Write-Host $t } function Abbruch($t) { Write-Host ""; Write-Host "✗ $t" -ForegroundColor Red; exit 1 } # --- 1. Plattform erkennen ------------------------------------------------- # ⛔ Unbekannt heisst ABBRUCH, nicht «wir nehmen mal amd64». Ein Programm fuer # die falsche Architektur scheitert mit einer Meldung, die niemand beim # Installationsprogramm sucht. # # ⚠️ PROCESSOR_ARCHITECTURE ist die Architektur des PROZESSES. Eine # 32-Bit-PowerShell auf einem 64-Bit-Windows meldet x86 -- deshalb wird # zusaetzlich PROCESSOR_ARCHITEW6432 gelesen, das genau in diesem Fall # gesetzt ist. Ohne das bekaeme ein Kunde «diese Architektur kennt Barry # nicht» auf einer Maschine, die wir bedienen. $roh = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } switch ($roh) { 'AMD64' { $arch = 'amd64' } 'ARM64' { $arch = 'arm64' } default { Abbruch "Diese Architektur ($roh) kennt Barry nicht. Melde dich bei uns." } } $datei = "barry-mcp-windows-$arch.exe" Sagen "Plattform: windows/$arch" # --- 2. Herunterladen ------------------------------------------------------ # In ein temporaeres Verzeichnis, das AUFGERAEUMT wird -- auch beim Abbruch. # Ein halb heruntergeladenes Programm im Zielverzeichnis waere schlimmer als # keines: es liegt im PATH und tut nicht, was es soll. $tmp = Join-Path ([System.IO.Path]::GetTempPath()) ("barry-mcp-" + [guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $tmp -Force | Out-Null try { Sagen "Lade $datei …" try { Invoke-WebRequest -Uri "$basis/dl/$datei" -OutFile "$tmp\$datei" -UseBasicParsing } catch { Abbruch "Der Download ist gescheitert. Ist $basis erreichbar?" } try { Invoke-WebRequest -Uri "$basis/checksums.txt" -OutFile "$tmp\checksums.txt" -UseBasicParsing } catch { Abbruch "Die Prüfsummen sind nicht erreichbar." } # --- 3. Pruefsumme -- VOR dem Installieren ------------------------------- # ⛔ Ohne diese Pruefung waere das hier ein Rohr in eine Shell, das ein # ungepruefetes Programm ablegt. Sie faengt den abgebrochenen Download und # die beschaedigte Zwischenspeicherung -- und sie gibt uns eine Stelle, an # der ein vertauschtes Programm auffaellt. $zeile = Select-String -Path "$tmp\checksums.txt" -Pattern ([regex]::Escape($datei) + '$') | Select-Object -First 1 if (-not $zeile) { Abbruch "Für $datei gibt es keine Prüfsumme. Das ist ein Fehler bei uns." } $soll = ($zeile.Line -split '\s+')[0] $ist = (Get-FileHash -Algorithm SHA256 -Path "$tmp\$datei").Hash if ($ist -ne $soll.ToUpper() -and $ist.ToLower() -ne $soll.ToLower()) { Abbruch "Die Prüfsumme passt nicht. erwartet: $soll bekommen: $ist Lade nicht weiter — melde dich bei uns." } Sagen "Prüfsumme stimmt." # --- 4. Installieren ----------------------------------------------------- New-Item -ItemType Directory -Path $ziel -Force | Out-Null $pfad = Join-Path $ziel 'barry-mcp.exe' # ⛔⛔ UNTER WINDOWS WIRD NICHT UEBERSCHRIEBEN, SONDERN UMBENANNT (Befund # eines Endnutzers, 18.09.). # # Sein Protokoll: # # Vorhanden: fcfa138 — wird ersetzt. # Move-Item : Eine Datei kann nicht erstellt werden, wenn sie bereits # vorhanden ist. # # Windows laesst eine Programmdatei, die gehalten wird, nicht ersetzen -- # und beim Aktualisieren ist sie fast immer gehalten: Claude Code faehrt # den MCP-Server, und wir selbst starten sie zwei Zeilen weiter oben, um # ihre Fassung zu lesen. `-Force` half nicht: es darf die Zieldatei nicht # loeschen. # # ⇒ UMBENENNEN ist erlaubt, auch bei einer laufenden Datei. Also: die alte # zur Seite, die neue an ihren Platz, die alte hinterher wegraeumen. Geht # das Wegraeumen nicht, weil sie noch laeuft, bleibt sie liegen und # verschwindet beim naechsten Mal -- das ist eine Datei zuviel und kein # Fehler. $beiseite = $null if (Test-Path $pfad) { # ⚠️ Die alte Fassung NENNEN. Wer nach einem Update nachsehen will, ob es # gewirkt hat, braucht sie im Vergleich. # ⛔ Die leere Eingabe ist das Gegenstueck zu `$null) if (-not $alt) { $alt = 'ohne Fassungsangabe' } Sagen "Vorhanden: $alt — wird ersetzt." $beiseite = "$pfad.alt-$(Get-Date -Format yyyyMMddHHmmss)" try { Move-Item -Path $pfad -Destination $beiseite -Force -ErrorAction Stop } catch { # ⛔ Wenn nicht einmal das Umbenennen geht, NENNEN wir den # wahrscheinlichen Halter. «Move-Item : IOException» ist die Meldung, # mit der der Kunde heute dasteht -- sie nennt weder Ursache noch # Ausweg, und er sucht den Fehler bei sich. Abbruch "Die vorhandene barry-mcp.exe laesst sich nicht ersetzen. Wahrscheinlich laeuft sie noch: Claude Code haelt den MCP-Server offen. Schliess Claude Code und fuehr diesen Befehl noch einmal aus." } } Move-Item -Path "$tmp\$datei" -Destination $pfad -Force # ⚠️ Bestes Bemuehen, kein Abbruch: die alte Datei kann noch laufen. Sie # liegen zu lassen ist harmlos, den Kunden deswegen abzuweisen nicht. if ($beiseite) { Remove-Item $beiseite -Force -ErrorAction SilentlyContinue } # ⛔ Windows markiert Heruntergeladenes (Zone.Identifier). Ohne diesen # Schritt kann SmartScreen den Start verweigern -- und zwar erst, wenn # Claude Code den Server startet, also weit weg von hier. try { Unblock-File -Path $pfad } catch { } # ⚠️ BARRY_MCP_OHNE_START ist fuer die Tests auf macOS/Linux (NCL-419): # dort kann pwsh eine .exe nicht ausfuehren und reicht sie ans System # weiter -- und das startete auf Retos Mac jedes Mal die Windows-VM. # Geprueft wird dort alles bis zur Ablage; der Start gehoert auf Windows. $ohneStart = ($env:BARRY_MCP_OHNE_START -eq '1') if ($ohneStart) { $fassung = 'nicht gestartet' } else { $fassung = ('' | & $pfad --version 2>$null) } if (-not $fassung) { $fassung = 'unbekannt' } Sagen "Installiert: $pfad ($fassung)" # --- 5. Nachweisen, dass es LAEUFT --------------------------------------- # ⛔ Nicht «Datei liegt da», sondern «Programm antwortet». Ein Handschlag # ueber stdio, und die Antwort muss ihn enthalten. Alles andere ist eine # Behauptung. if (-not $ohneStart) { $handschlag = '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' $antwort = ($handschlag | & $pfad 2>$null) -join '' if ($antwort -notmatch '"name":"barry"') { Abbruch "Das Programm läuft nicht auf dieser Maschine. Melde dich bei uns und nenne: windows/$arch." } Sagen "Das Programm antwortet." } } finally { Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue } # --- 6. PATH --------------------------------------------------------------- # ⛔ Ueber die .NET-Schnittstelle und NICHT mit `setx`: setx schneidet den PATH # bei 1024 Zeichen ab, und ein abgeschnittener Benutzer-PATH ist ein Schaden, # der nichts mit Barry zu tun hat und uns zugeschrieben wird. # # ⚠️ Der PATH der LAUFENDEN Sitzung wird zusaetzlich gesetzt, sonst findet ein # `claude mcp add` im selben Fenster das Programm nicht -- und der Kunde liest # «command not found», obwohl die Installation gelungen ist. $benutzerPfad = [Environment]::GetEnvironmentVariable('Path', 'User') if (-not $benutzerPfad) { $benutzerPfad = '' } $teile = $benutzerPfad -split ';' | Where-Object { $_ -ne '' } if ($teile -notcontains $ziel) { [Environment]::SetEnvironmentVariable('Path', (($teile + $ziel) -join ';'), 'User') Sagen "$ziel in deinen PATH aufgenommen." Sagen "⚠ Offene Fenster kennen ihn noch nicht — dort einmal neu öffnen." } if (($env:Path -split ';') -notcontains $ziel) { $env:Path = "$env:Path;$ziel" } # --- 7. Was jetzt zu tun ist ----------------------------------------------- Sagen "" Sagen "Fertig. Zwei Schritte noch:" Sagen "" Sagen "1) Schlüssel holen auf https://console.barry.build/mcp" Sagen " und Barry anmelden — EINE Zeile, ohne Zeilenumbruch:" Sagen "" Sagen " claude mcp add --scope user barry --env BARRY_TOKEN=bry_DEIN_SCHLUESSEL -- barry-mcp" Sagen "" Sagen " --scope user, damit Barry in JEDEM Projekt da ist. Ohne das gilt es" Sagen " nur im Verzeichnis, in dem du den Befehl ausführst." Sagen "" Sagen "2) Claude Code EINMAL neu starten. MCP-Server werden beim Start" Sagen " verbunden — ohne Neustart ist Barry nicht da." Sagen "" Sagen "Danach: «welche Apps habe ich bei Barry?»"