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.
Endpunkt und Transport
Abschnitt betitelt „Endpunkt und Transport“| Punkt | Wert |
|---|---|
| URL | /mcp/ auf dem Host des Portals (/mcp geht auch). Die Seite API keys & agents zeigt die vollständige URL. |
| Transport | Streamable 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. |
| Protokollversionen | 2025-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). |
| Methoden | initialize, ping, tools/list, tools/call |
| Server | Name 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. |
| Anmeldung | Authorization: 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. |
| Browser | Ein Origin-Header muss der eigene Host des Portals sein oder einer, den das Portal erlaubt (sonst 403). |
| Tool-Liste | tools/list zeigt nur die Tools, die die Scopes des Schlüssels erlauben. |
Die Tools
Abschnitt betitelt „Die Tools“„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.
| Tool | Scope | Admin | Eingabe | Ausgabe |
|---|---|---|---|---|
list_clusters | k3s:read | — | keine | {items}: bis zu 100 Cluster |
get_cluster | k3s: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_snapshots | k3s:read | — | cluster*, limit (1–100, Standard 20) | {items, truncated}, neueste zuerst, eine Zeile pro Kopie (local, s3) |
create_snapshot | k3s:write | ja | cluster* | die eingereihte Operation |
list_operations | k3s:read | — | cluster*, limit, state, type | {items, truncated}, neueste zuerst |
get_operation | k3s:read | — | cluster*, operation_id* | die Operation mit ihren Ereignissen |
schedule_upgrade | k3s:write | ja | cluster*, when* (window oder now), release | die eingereihte Operation |
list_addons | k3s:read | — | cluster* | die Add-ons des Release: an oder aus, Optionen, optionsSchema, requires, conflicts, Speicher, was der Cluster gemeldet hat |
set_addon | k3s:write | ja | cluster*, addon*, enabled, options, also | {addon, switched, generation, note} |
request_kubeconfig | k3s:access | für admin, wenn das Team es Mitgliedern nicht erlaubt | cluster*, public_key*, role (view Standard, oder admin), lifetime_seconds (600–86400, Standard 3600) | die eingereihte Operation und ihre operation_id |
get_kubeconfig_result | k3s: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_access | k3s:access | für alle außer der Besitzerin oder dem Besitzer des Schlüssels | cluster*, user (me Standard, all oder die ID oder E-Mail eines Mitglieds) | die eingereihte Operation |
list_projects | k3s:read | — | keine | {items}: die Hetzner-Projekte des Teams, {id, name, ref} |
list_server_types | k3s: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_cluster | k3s:destructive | ja | name*, confirm*, project* und die optionalen Felder unten | {cluster, next}; das Anlegen läuft im Hintergrund |
delete_cluster | k3s:destructive | ja | cluster*, confirm*, final_snapshot (Standard true) | {cluster, next}; der Cluster zählt sofort nicht mehr für die Abrechnung |
restore_snapshot | k3s:destructive | ja | cluster*, snapshot*, confirm* | die eingereihte Operation |
detach_cluster | k3s:destructive | ja | cluster*, 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.
Die optionalen Eingaben von create_cluster
Abschnitt betitelt „Die optionalen Eingaben von create_cluster“| Eingabe | Werte |
|---|---|
slug | das DNS-Label, Kleinbuchstaben, Ziffern und Bindestriche, bis zu 32; aus dem Namen gebildet |
location, server_type | aus list_server_types |
adopt_server | ein Server, den du schon hast: id*, confirm_name* (sein Name, getippt: Er wird neu aufgesetzt), keep_volumes, detach_firewalls |
channel | stable (Standard) oder early |
topology | single |
maintenance | days (mindestens ein Wochentag), start und end als HH:MM, timezone |
allowed_api_ranges | CIDRs, die die Kubernetes-API erreichen dürfen; Standard alle (0.0.0.0/0, ::/0) |
backup | holder (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_token | mode (separate Standard, oder copy), token |
platform | profile*, 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).
Bestätigung
Abschnitt betitelt „Bestätigung“Die vier zerstörerischen Tools brauchen k3s:destructive, einen Team-Admin als Besitzer des Schlüssels und confirm:
delete_cluster,restore_snapshot,detach_cluster: dennamedes 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).
Ergebnisse und Ablehnungen
Abschnitt betitelt „Ergebnisse und Ablehnungen“| Fall | Was der Client bekommt |
|---|---|
| Erfolg | Ein 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. |
| Ablehnung | Ein 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 passt | validation_failed, mit errors, das jedes Feld listet. Die Schemas erlauben keine zusätzlichen Felder. |
| Zu viele Aufrufe | rate_limited, mit retryAfterSeconds. |
| Unbekanntes Tool | JSON-RPC-Fehler -32602. |
| Unbekannte Methode | JSON-RPC-Fehler -32601. |
| Keine JSON-RPC-2.0-Nachricht | JSON-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:
- 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.pemgibt den öffentlichen Schlüssel aus. Der Helfer liegt unter/mcp/paasbox_kubeconfig.pyund braucht Python 3.10 oder neuer und das Paketcryptography. request_kubeconfigmit diesem öffentlichen Schlüssel.pbx-agentauf dem Cluster stellt eine Kubeconfig mit einem Token aus, das nachlifetime_secondsabläuft, und verschlüsselt sie für den Schlüssel: ECDH, HKDF-SHA256 (32 Null-Bytes als Salt, Infopbx-access-v1), AES-256-GCM mit der Operation-ID als zugehörigen Daten.get_kubeconfig_result, bisreadytrueist. Es gibt die versiegelte Kubeconfig einmal heraus, an denselben Schlüssel, innerhalb von 5 Minuten; danach antwortet esgone.- 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.
Rate-Limits und Audit
Abschnitt betitelt „Rate-Limits und Audit“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.