diff --git a/README.md b/README.md index 98c6694..8fec920 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ keine Modell-Tokens und verraten dem Modell keine zusätzlichen Daten. - [`docs/PLATFORM_OVERVIEW.md`](docs/PLATFORM_OVERVIEW.md) – kurze Gesamtsicht - [`docs/QWEN_OPERATOR_CONTEXT.md`](docs/QWEN_OPERATOR_CONTEXT.md) – ausführliches Kontextpaket für das lokale Operator-Modell - [`docs/PLATFORM_CONTEXT_MCP.md`](docs/PLATFORM_CONTEXT_MCP.md) – profilunabhängiges Plattformwissen und kontrollierte Dokumentationspflege +- [`docs/GITHUB_MCP.md`](docs/GITHUB_MCP.md) – sicherer GitHub-Nur-Lesen-Betrieb und bewusst aktivierbarer Wartungsmodus - [`config/operator-system-prompt.txt`](config/operator-system-prompt.txt) – knapper System-Prompt für ein getrenntes Operator-Profil - [Roadmap für den neuen Host](docs/NEW_HOST_ROADMAP.md) diff --git a/docs/GITHUB_MCP.md b/docs/GITHUB_MCP.md new file mode 100644 index 0000000..696b637 --- /dev/null +++ b/docs/GITHUB_MCP.md @@ -0,0 +1,78 @@ +# GitHub MCP: sicherer Lese- und Wartungsmodus + +## Normalbetrieb + +Athena startet den offiziellen GitHub MCP grundsätzlich im Nur-Lesen-Modus. +Sichtbar sind exakt: + +- `search_repositories` +- `get_repository_tree` +- `get_file_contents` +- `search_code` + +Der Token liegt ausschließlich in `/etc/mike-ai/github-mcp.env` (Modus 0600). +Er steht weder in Open WebUI noch in Git, der Dokumentation oder dem Platform +Context MCP. Der Container besitzt keinen Host-Port. + +Status anzeigen: + +```bash +sudo /opt/mike-ai/stack/platform/mcp/github-mcp-mode.sh status +``` + +## Bewusster Wartungstermin mit Schreibzugriff + +Wenn Dateien in einem eigenen Repository geändert werden sollen, aktiviert der +Administrator den begrenzten Wartungsmodus: + +```bash +sudo /opt/mike-ai/stack/platform/mcp/github-mcp-mode.sh maintenance --confirm +``` + +Zusätzlich zu den Lesewerkzeugen werden nur diese Operationen angeboten: + +- Branches auflisten und einen neuen Branch anlegen +- eine oder mehrere Dateien committen +- einen Pull Request anlegen + +Absichtlich fehlen Löschen, Mergen, Repository-Erstellung, Workflow-Ausführung, +Issue-Veränderungen und administrative Werkzeuge. Trotzdem ist dies echter +Schreibzugriff. Vor jeder Änderung muss das Modell den aktuellen Dateiinhalt +lesen, auf einem neuen Branch arbeiten und Ziel, Dateien und Wirkung nennen. + +Nach der Arbeit sofort zurückschalten: + +```bash +sudo /opt/mike-ai/stack/platform/mcp/github-mcp-mode.sh read +``` + +Beide Umschaltungen starten nur den GitHub-MCP-Container neu und danach kurz +das Open-WebUI-Backend, damit dessen Werkzeugcache sicher zum aktiven Modus +passt. LLM-Profile, Router, VPN und andere MCPs werden nicht neu gestartet. + +## Token-Rechte + +Die serverseitige Werkzeugliste ersetzt keine saubere Tokenbegrenzung. Für den +Normalbetrieb ist ein nur lesender Fine-grained PAT ideal. Ein Token, der auch +schreiben darf, sollte nur Zugriff auf ausdrücklich ausgewählte Repositories und +den geringsten benötigten `Contents`-Umfang erhalten. Geschützte Hauptbranches +und verpflichtende Pull Requests bilden die zweite Schutzschicht. + +Nach Tokenwechsel oder Rechteänderung: + +```bash +sudo /opt/mike-ai/stack/platform/mcp/github-mcp-mode.sh read +``` + +## Fehlerbehebung + +`Failed to connect to MCP server 'github-local'` war am 23. August 2026 kein +Tokenfehler. Supergateway beantwortete den regulären MCP-Handshake von Open +WebUI fehlerhaft. Produktiv wird deshalb der offizielle GitHub MCP 1.10.1 über +`mcp-proxy` 0.12.0 bereitgestellt. Der Pfad wurde mit Open WebUIs eigenem +Python-MCP-Client und einer echten öffentlichen Repositorysuche geprüft. + +Der Normalmodus ist Teil des Installationsskripts. Skript, Compose-Override und +diese Anleitung liegen im Git-Repository und werden vom Recovery-Koffer +mitgeführt. Das Platform Context MCP kann diese Anleitung lesen, erhält aber +weder Token noch die Fähigkeit, den Modus selbst unbemerkt umzuschalten. diff --git a/docs/QWEN_OPERATOR_CONTEXT.md b/docs/QWEN_OPERATOR_CONTEXT.md index 217422c..6744861 100644 --- a/docs/QWEN_OPERATOR_CONTEXT.md +++ b/docs/QWEN_OPERATOR_CONTEXT.md @@ -249,6 +249,12 @@ WebUI, Git oder einem Prompt. Für Quellcode, README, API-Routen und Repositorystruktur ist GitHub das richtige Werkzeug; die allgemeine Websuche ist für breitere öffentliche Recherche zuständig. +GitHub ist standardmäßig strikt lesend. Falls der Benutzer ausdrücklich einen +beaufsichtigten Schreibtermin verlangt, gilt der Ablauf in +`docs/GITHUB_MCP.md`: begrenzten Wartungsmodus aktivieren, ausschließlich auf +einem neuen Branch arbeiten, die Änderung prüfen und danach sofort zu +Nur-Lesen zurückkehren. Der Modus darf niemals stillschweigend erweitert werden. + ## 10. Verfahren zum Hinzufügen eines MCPs 1. Bedarf und Vertrauensgrenze definieren. Prüfe zuerst, ob ein offizieller, diff --git a/platform/mcp/compose.github-maintenance.yaml b/platform/mcp/compose.github-maintenance.yaml new file mode 100644 index 0000000..6f32790 --- /dev/null +++ b/platform/mcp/compose.github-maintenance.yaml @@ -0,0 +1,12 @@ +services: + mcp-github: + # Temporary, operator-controlled maintenance mode. It deliberately omits + # delete, merge, repository creation, issue mutation and workflow tools. + command: + - /usr/local/bin/github-mcp-server + - stdio + - --tools + - search_repositories,get_repository_tree,get_file_contents,search_code,list_branches,create_branch,create_or_update_file,push_files,create_pull_request + environment: + GITHUB_READ_ONLY: "0" + GITHUB_TOOLS: search_repositories,get_repository_tree,get_file_contents,search_code,list_branches,create_branch,create_or_update_file,push_files,create_pull_request diff --git a/platform/mcp/github-mcp-mode.sh b/platform/mcp/github-mcp-mode.sh new file mode 100755 index 0000000..bb3a874 --- /dev/null +++ b/platform/mcp/github-mcp-mode.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +MODE=${1:-} +CONFIRM=${2:-} +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +PROJECT=mike-ai-tools +BASE=(docker compose -p "$PROJECT" --profile github -f "$ROOT_DIR/compose.yaml") +MAINTENANCE=(-f "$ROOT_DIR/compose.github-maintenance.yaml") + +die() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; } +[[ $EUID -eq 0 ]] || die "Bitte als root ausführen." + +case "$MODE" in + read) + "${BASE[@]}" up -d --no-deps --force-recreate mcp-github + ;; + maintenance) + [[ $CONFIRM == --confirm ]] || die \ + "Wartungsmodus nur mit: $0 maintenance --confirm" + "${BASE[@]}" "${MAINTENANCE[@]}" up -d --no-deps --force-recreate mcp-github + ;; + status) + command_line=$(docker inspect -f '{{json .Config.Cmd}}' mike-ai-mcp-github 2>/dev/null || true) + if [[ $command_line == *create_branch* ]]; then + printf 'GitHub MCP: WARTUNGSMODUS (begrenzter Schreibzugriff)\n' + elif [[ $command_line == *--read-only* ]]; then + printf 'GitHub MCP: NUR LESEN\n' + else + die "GitHub-MCP-Modus ist nicht eindeutig; Konfiguration prüfen." + fi + exit 0 + ;; + *) + die "Aufruf: $0 {status|read|maintenance --confirm}" + ;; +esac + +# Open WebUI caches MCP capabilities. A short backend restart makes the new +# allowlist deterministic for all profiles without touching model services. +docker restart mike-ai-open-webui >/dev/null +for _ in $(seq 1 30); do + [[ $(docker inspect -f '{{.State.Health.Status}}' mike-ai-mcp-github 2>/dev/null || true) == healthy ]] && break + sleep 1 +done +[[ $(docker inspect -f '{{.State.Health.Status}}' mike-ai-mcp-github 2>/dev/null || true) == healthy ]] || \ + die "GitHub MCP wurde nicht gesund. Zurücksetzen mit: $0 read" + +"$0" status