Zum Inhalt springen

MCP-Tools

Der MCP-Server von PaaSbox Clusters gibt einem Coding-Agenten, etwa Claude Code oder einem anderen MCP-Client, die Cluster-Operationen des Portals als Tools. Diese Seite listet den Endpunkt, wie ein Aufruf angemeldet wird, und jedes Tool mit Scope, Eingabe, Ausgabe und dem, was es ablehnt.

PunktWert
URL/mcp/ auf dem Host des Portals (/mcp geht auch). Die Seite API keys & agents zeigt die vollständige URL.
TransportStreamable HTTP, zustandslos, Antworten als JSON. Per POST geht eine JSON-RPC-2.0-Nachricht oder ein Batch: Eine Anfrage bekommt 200 mit ihrer Antwort, eine Benachrichtigung 202. GET und DELETE antworten 405: Es gibt keinen Event-Stream und keine Sitzung.
Protokollversionen2025-11-25 (die neueste), 2025-06-18, 2025-03-26, 2024-11-05. initialize antwortet mit der Version des Clients, wenn sie dazugehört, sonst mit der neuesten; ein Header MCP-Protocol-Version muss eine davon nennen (sonst 400).
Methodeninitialize, ping, tools/list, tools/call
ServerName paasbox-clusters, Titel „PaaSbox Clusters“. Seine instructions nennen dem Agenten sein Team, seine Person und Rolle, die Scopes des Schlüssels und die Regeln unten.
AnmeldungAuthorization: Bearer <key> bei jeder Anfrage, ein API-Schlüssel des Teams (Einem Agenten Zugriff geben). Kein Schlüssel, ein unbekannter, widerrufener oder abgelaufener, oder einer, dessen Besitzer kein aktives Mitglied des Teams mehr ist: 401 mit WWW-Authenticate: Bearer. Ein Schlüssel ohne k3s-Scope, oder ein Team ohne PaaSbox Clusters: 403.
BrowserEin Origin-Header muss der eigene Host des Portals sein oder einer, den das Portal erlaubt (sonst 403).
Tool-Listetools/list zeigt nur die Tools, die die Scopes des Schlüssels erlauben.

„Admin“ heißt: Die Besitzerin oder der Besitzer des Schlüssels muss Team-Admin sein. Jedes Tool, das cluster nimmt, nimmt den Slug des Clusters (sein DNS-Label) oder seine ID. Eine Pflichteingabe ist mit * markiert.

ToolScopeAdminEingabeAusgabe
list_clustersk3s:read—keine{items}: bis zu 100 Cluster
get_clusterk3s:read—cluster*der Cluster vollständig: Zustand und Gesundheit, Nodes, die laufende Operation, der letzte Snapshot, das Backup-Ziel, das Wartungsfenster, das angebotene Upgrade (upgrade.available)
list_snapshotsk3s:read—cluster*, limit (1–100, Standard 20){items, truncated}, neueste zuerst, eine Zeile pro Kopie (local, s3)
create_snapshotk3s:writejacluster*die eingereihte Operation
list_operationsk3s:read—cluster*, limit, state, type{items, truncated}, neueste zuerst
get_operationk3s:read—cluster*, operation_id*die Operation mit ihren Ereignissen
schedule_upgradek3s:writejacluster*, when* (window oder now), releasedie eingereihte Operation
list_addonsk3s:read—cluster*die Add-ons des Release: an oder aus, Optionen, optionsSchema, requires, conflicts, Speicher, was der Cluster gemeldet hat
set_addonk3s:writejacluster*, addon*, enabled, options, also{addon, switched, generation, note}
request_kubeconfigk3s:accessfür admin, wenn das Team es Mitgliedern nicht erlaubtcluster*, public_key*, role (view Standard, oder admin), lifetime_seconds (600–86400, Standard 3600)die eingereihte Operation und ihre operation_id
get_kubeconfig_resultk3s:access—cluster*, operation_id*{operationId, state, ready: false, retryAfterSeconds}, dann einmal {operationId, state, ready: true, sealed, aad, expiresAt, decrypt}; decrypt beschreibt, wie man sie öffnet
revoke_accessk3s:accessfür alle außer der Besitzerin oder dem Besitzer des Schlüsselscluster*, user (me Standard, all oder die ID oder E-Mail eines Mitglieds)die eingereihte Operation
list_projectsk3s:read—keine{items}: die Hetzner-Projekte des Teams, {id, name, ref}
list_server_typesk3s:read—project*, location (Standard fsn1)die Standorte des Projekts und die an einem davon angebotenen Servertypen, mit Speicher und Hetzners monatlichem Nettopreis in EUR
create_clusterk3s:destructivejaname*, confirm*, project* und die optionalen Felder unten{cluster, next}; das Anlegen läuft im Hintergrund
delete_clusterk3s:destructivejacluster*, confirm*, final_snapshot (Standard true){cluster, next}; der Cluster zählt sofort nicht mehr für die Abrechnung
restore_snapshotk3s:destructivejacluster*, snapshot*, confirm*die eingereihte Operation
detach_clusterk3s:destructivejacluster*, confirm*{cluster, next}

Eine eingereihte Operation kommt als {operation, operation_id, next} zurück. pbx-agent holt sie bei seiner nächsten Synchronisation ab, etwa alle 30 Sekunden: Frag get_operation ab, bis ihr state succeeded oder failed ist.

Die lesenden Tools tragen die MCP-Annotation readOnlyHint; create_cluster, delete_cluster, restore_snapshot und detach_cluster tragen destructiveHint.

EingabeWerte
slugdas DNS-Label, Kleinbuchstaben, Ziffern und Bindestriche, bis zu 32; aus dem Namen gebildet
location, server_typeaus list_server_types
adopt_serverein Server, den du schon hast: id*, confirm_name* (sein Name, getippt: Er wird neu aufgesetzt), keep_volumes, detach_firewalls
channelstable (Standard) oder early
topologysingle
maintenancedays (mindestens ein Wochentag), start und end als HH:MM, timezone
allowed_api_rangesCIDRs, die die Kubernetes-API erreichen dürfen; Standard alle (0.0.0.0/0, ::/0)
backupholder (portal Standard, oder customer), s3 (endpoint, bucket, folder, region, access_key, secret_key), schedule_cron (fünf Cron-Felder, UTC), keep_cycles (1–500)
hcloud_tokenmode (separate Standard, oder copy), token
platformprofile*, observability. Seit paasbox-platform 1.0.2 (Release 2026.10.2) braucht die Plattform eine ACME-E-Mail (acmeEmail), die create_cluster nicht übergeben kann, darum wird ein Anlegen mit platform mit validation_failed abgelehnt. Leg den Cluster ohne platform an und schalte die Plattform mit set_addon an: addon paasbox-platform, enabled true, options mit profile und acmeEmail, also ["flux"]

Es gelten die Prüfungen der Anlegen-Seite, in ihrer Reihenfolge: ein verbundenes Projekt, ein angebotenes Release im Kanal stable, das Cluster-Limit des Teams von 10 (quota_exceeded), die akzeptierten Bedingungen und die Abrechnung. Der erste Cluster eines Teams startet sein Abonnement und wird im Portal angelegt, nicht über ein Tool (payment_method_required); ebenso der erste Cluster, nachdem das Abonnement des Teams geendet hat. Geprüft wird gegen das Release im Kanal stable, auch bei channel early, und platform wird abgelehnt, solange das Add-on eine E-Mail braucht, die das Tool nicht übergeben kann (siehe oben).

Die vier zerstörerischen Tools brauchen k3s:destructive, einen Team-Admin als Besitzer des Schlüssels und confirm:

  • delete_cluster, restore_snapshot, detach_cluster: den name des Clusters (nicht seinen Slug), exakt;
  • create_cluster: den Namen des neuen Clusters, noch einmal getippt.

Die Anweisungen des Servers sagen dem Agenten, dass er dich fragen soll, bevor er confirm setzt. Ob er es getan hat, kann das Portal nicht prüfen; es prüft den Namen. Ob du gefragt wirst, hängt von deinem MCP-Client ab und davon, wie du ihn eingerichtet hast.

Ein Schlüssel mit k3s:destructive reicht an jeden Cluster seines Teams. Damit ein Agent, der Wegwerf-Cluster anlegt, nicht an die Produktion kommt, halte die Produktion in einem Team, zu dem der Schlüssel nicht gehört (Leitplanken für Agenten).

FallWas der Client bekommt
ErfolgEin Tool-Ergebnis mit der Antwort als JSON-Text und als structuredContent, isError: false. Text über 64 KiB wird abgeschnitten, mit dem Hinweis, den Aufruf einzugrenzen.
AblehnungEin Tool-Ergebnis mit isError: true: der Text <code>: <detail> und das Problem-Dokument (type, title, status, detail, code, field und zusätzliche Felder) als structuredContent. Die Codes sind die der REST-API (REST-API › Fehler).
Eingabe, die nicht zum Schema passtvalidation_failed, mit errors, das jedes Feld listet. Die Schemas erlauben keine zusätzlichen Felder.
Zu viele Aufruferate_limited, mit retryAfterSeconds.
Unbekanntes ToolJSON-RPC-Fehler -32602.
Unbekannte MethodeJSON-RPC-Fehler -32601.
Keine JSON-RPC-2.0-NachrichtJSON-RPC-Fehler -32600; ein Body, der kein JSON ist: -32700 mit HTTP 400.

Kubeconfigs, versiegelt für den Schlüssel des Agenten

Abschnitt betitelt „Kubeconfigs, versiegelt für den Schlüssel des Agenten“

Eine Kubeconfig reist nie im Klartext, und das Portal kann sie nicht lesen:

  1. Der Agent erzeugt ein kurzlebiges ECDH-P-256-Schlüsselpaar und behält die private Hälfte. Der Helfer des Portals erledigt das: python3 paasbox_kubeconfig.py keygen --out key.pem gibt den öffentlichen Schlüssel aus. Der Helfer liegt unter /mcp/paasbox_kubeconfig.py und braucht Python 3.10 oder neuer und das Paket cryptography.
  2. request_kubeconfig mit diesem öffentlichen Schlüssel. pbx-agent auf dem Cluster stellt eine Kubeconfig mit einem Token aus, das nach lifetime_seconds abläuft, und verschlüsselt sie für den Schlüssel: ECDH, HKDF-SHA256 (32 Null-Bytes als Salt, Info pbx-access-v1), AES-256-GCM mit der Operation-ID als zugehörigen Daten.
  3. get_kubeconfig_result, bis ready true ist. Es gibt die versiegelte Kubeconfig einmal heraus, an denselben Schlüssel, innerhalb von 5 Minuten; danach antwortet es gone.
  4. Der Agent speichert das JSON des Ergebnisses und entschlüsselt es lokal: python3 paasbox_kubeconfig.py decrypt --key key.pem < result.json > kubeconfig.

Die Anweisungen sagen dem Agenten, dass er weder den privaten Schlüssel noch die entschlüsselte Kubeconfig in die Unterhaltung schreiben darf.

Ein Schlüssel darf 120 Aufrufe pro Minute machen, davon 20 Aufrufe von Tools, die nicht nur lesen, darunter request_kubeconfig, get_kubeconfig_result und revoke_access; die Zähler sind dieselben wie bei der REST-API. Jeder Tool-Aufruf wird festgehalten, Ablehnungen und unbekannte Tools eingeschlossen, mit Schlüssel, Person, Tool, Cluster, den Argumenten ohne Geheimnisse und dem Ergebnis. Die Admins des Teams lesen es auf API keys & agents (Einem Agenten Zugriff geben).

Leitplanken für Agenten sagt, was diese Regeln verhindern und was nicht.