# Die volle REST-API von Xen Orchestra 6.5 — 245 Tools aus einer DADL

> Xen Orchestra 6.4 hat seine REST-API stabilisiert, 6.5 hat PATCH-Updates und VM-Controller ergänzt. Vates liefert einen eigenen MCP-Server — 7 Tools, bewusst read-only. Wir haben einen anderen Schnitt gewählt: die gesamte 245-Endpoint-Oberfläche, lesend und schreibend, als eine DADL. Beide gehören in dieselbe Registry. Hier ist, warum.

Canonical: https://www.toolmesh.io/de/blog/xen-orchestra-full-rest-api-in-one-dadl/

Xen Orchestra hat die letzten beiden Releases darauf verwendet, seine REST-API zu etwas zu machen, auf dem man aufbauen kann. [XO 6.4](https://xen-orchestra.com/blog/) (April 2026) hat `/rest/v0/` als stabil markiert und fein granulares RBAC v2 ergänzt; 6.5 hat `PATCH /vms/{id}` für partielle VM-Updates und eine eigene `/vm-controllers`-Collection hinzugefügt. Im Februar hat Vates außerdem einen [eigenen MCP-Server](https://xen-orchestra.com/blog/mcp-meets-xen-orchestra/) mit XO 6.2 ausgeliefert — sieben Tools, bewusst read-only, damit Teams ihn vom ersten Tag an in der Produktion aktivieren können.

Wir haben einen anderen Schnitt derselben API gewählt. Die DADL für Xen Orchestra deckt die **gesamte 245-Endpoint-REST-Oberfläche** ab — lesend und schreibend — als eine YAML-Datei. Dieser Post ist das Build-Log und eine ehrliche Antwort auf die naheliegende Frage: Warum zwei MCP-Oberflächen für dasselbe Produkt?

## Was die REST-API jetzt abdeckt

Die XO REST-API ist längst keine dünne Leseschicht mehr. Ab 6.5 exponiert sie den vollständigen Objektgraphen — VMs (inklusive `PATCH`-Teilupdates und Snapshot-Revert), VM-Controller, VM-Templates, VM-/VDI-Snapshots, Hosts, Pools, Storage (SR/VDI/VBD), Netzwerk (VIF/PIF/PBD), Hardware-Passthrough (PCI/PGPU/SM) — dazu jede Lifecycle-Aktion: Power, Snapshot, Clone, Migration, Export/Import, Hotplug. Über den Objekten liegen die operativen Oberflächen: Tasks, Backups (Jobs, Logs, Repositories, Restore, Schedules), Echtzeit-Änderungsevents über Server-Sent Events, RBAC v2 (Users, Groups, ACL-Roles, ACL-Privileges) und Host-/Pool-Wartung (Rolling Reboot, Rolling Update, Emergency Shutdown).

Das ist eine große API, und fast alles davon verändert Infrastruktur. Nichts von der Schreibseite ist über den eigenen MCP-Server erreichbar — by design, nicht aus Versehen.

## Die Zahlen

| | DADL (`xen-orchestra.dadl`) | `@xen-orchestra/mcp` (Vates, eigen) |
|---|---|---|
| Tools | **245** | 7 |
| Umfang | lesend **und** schreibend | read-only by design |
| Coverage | jedes REST-Objekt + Lifecycle-Aktion, Backups, RBAC v2, SSE-Events, SDN-Traffic-Rules, Dashboards, Auth-Tokens | Infrastruktur-Summary, Pools / Hosts / VMs auflisten und inspizieren, Pool-Dashboard, Dokumentationssuche |
| Create / Start / Migration / Delete? | ja | nein — bewusst |
| Verteilung | eine 245-Tool-YAML-Datei | Node-Server, mitgeliefert ab XO 6.2 |
| Einem neuen API-Release folgen | ~30 Zeilen YAML pro Endpoint | kommt mit dem XO-Release |
| Governance-Schicht | Credentials, Autorisierung, Audit (über ToolMesh) | keine — lokal, in-process |

Die lokale Validierung, ausgeführt aus dem Registry-Checkout:

```
> cd dadl-registry && npm run validate
✅ xen-orchestra.dadl — 245 tools
```

Quelle auf GitHub: [`dadl-registry/xen-orchestra.dadl`](https://github.com/DunkelCloud/dadl-registry/blob/main/xen-orchestra.dadl). Live in der Registry unter [dadl.ai/d/xen-orchestra](https://dadl.ai/d/xen-orchestra). Die DADL-Spezifikation selbst: [dadl.ai/spec](https://dadl.ai/spec/dadl-spec-v0.1.md).

## Ein durchgespieltes Beispiel: eine VM-Änderung, rückgängig machbar

Der Sinn der Schreibseite ist, dass sie Infrastruktur tatsächlich verändert — sicher, mit Spur. Hier ist ein Round-Trip aus drei Calls: eine laufende VM finden, sie snapshotten, damit die Änderung umkehrbar ist, und sie dann patchen.

```js
// 1. Find the VM by name (XO filter syntax, compact fields)
const [vm] = await toolmesh.xen_orchestra_list_vms({
  filter: "name_label:web-fra-01",
  fields: "uuid,name_label,tags"
});

// 2. Snapshot first, so the change is undoable
await toolmesh.xen_orchestra_snapshot_vm({
  id: vm.uuid,
  name_label: `pre-change ${new Date().toISOString().slice(0, 10)}`
});

// 3. PATCH the live VM — tags is a hot field, applied while running (XO 6.5)
await toolmesh.xen_orchestra_update_vm({
  id: vm.uuid,
  tags: [...vm.tags, "managed:toolmesh"]
});
```

Drei Calls. Kein Glue-Code. Schritt 2 und 3 sind genau das, was ein read-only MCP-Server nicht kann — und die DADL übernimmt transparent:

- die ungewöhnliche cookie-basierte Authentifizierung (der Token wird serverseitig als `Cookie: authenticationToken=…` injiziert — das Modell sieht ihn nie);
- das async-by-default-Aktionsmodell — die meisten Writes geben eine Task-Referenz zurück; `sync` setzt man nur für kurze Operationen, und für lange (Migration, Export) pollt man `get_task`, um HTTP-Client-Timeouts zu vermeiden;
- die Cold-vs-Hot-Field-Unterscheidung bei `update_vm` — `memoryStaticMax`, `cpusStaticMax`, `secureBoot` brauchen eine heruntergefahrene VM, während `tags`, `nameLabel` und `cpus` live greifen (das Beispiel nutzt `tags`, läuft also ohne Downtime);
- Retries bei transienten Fehlern und terminale Klassifizierung für `404` ("no such VM") und RBAC-`403`.

Dieselben Calls aus Claude oder jedem anderen Agenten. Kein Xen-Orchestra-spezifischer Code auf der Client-Seite.

## Read-only ist ein Feature, keine Lücke

Das naheliegende Framing — "245 schlägt 7" — ist das falsche. Die beiden Oberflächen beantworten verschiedene Fragen.

Der eigene MCP-Server von Vates ist *absichtlich* read-only. Er läuft in-process, kommt mit XO mit, braucht keine externe Infrastruktur und kann nichts kaputt machen. Wenn die Frage lautet *"lass einen Assistenten meine Infrastruktur ansehen und Fragen dazu beantworten"*, ist das die richtige Form, und man sollte ihn nutzen. Wir versuchen nicht, ihn zu ersetzen — die DADL enthält sogar ein `get_mcp_status`-Tool, das meldet, ob XOs eigener eingebauter MCP-Server aktiviert ist.

Die DADL beantwortet eine andere Frage: *"lass einen Agenten meine Infrastruktur betreiben — erstellen, patchen, snapshotten, migrieren, sichern, RBAC provisionieren — ohne ihm rohe Admin-Credentials zu geben."* Das ergibt nur mit einer Kontrollschicht darunter Sinn. Über ToolMesh läuft jedes der 245 Tools hinter zentralisierten Credentials (der XO-Token erreicht das Modell nie), Autorisierung (ein Agent kann `list_vms` und `snapshot_vm` erhalten, aber nicht `delete_sr`) und einem Audit-Log (jeder Call protokolliert mit Was, Wann und Warum). Die Schreibseite ist der ganze Punkt, und die Governance-Schicht ist das, was die Schreibseite sicher exponierbar macht.

Beide Definitionen liegen in derselben Registry. Sie sind Ergänzungen: read-only-Discovery in-process, vollständiges Lifecycle-Management über ein governtes Gateway.

## Der API hinterherzukommen ist ein YAML-Diff

XO 6.4 hat RBAC v2 ergänzt; 6.5 hat `PATCH /vms/{id}`, `/vm-controllers` und einen REST-Snapshot-Revert-Endpoint hinzugefügt. Jedes davon in der DADL nachzuziehen ist dieselbe kleine Arbeitseinheit: `xen-orchestra.dadl` öffnen, den Tool-Block ergänzen (~30 Zeilen YAML pro Endpoint), `npm run validate` laufen lassen, einen PR aufmachen, das Diff reviewen, mergen. ToolMesh nimmt die neuen Tools beim nächsten Reload auf. Keine SDK-Änderungen, kein Release zum Schnüren, kein npm-Publish, kein "bitte upgraden" an die Nutzer.

Zwei konkrete Beispiele aus dem aktuellen Release:

- 6.5 hat `POST /vms/{id}/actions/revert_snapshot` für automatisierbaren Snapshot-Revert ausgeliefert. Die DADL führt ihn bereits als `revert_vm_to_snapshot`, annotiert mit *"requires XO 6.5+ (route returns 404 on older builds)"* — gegen einen älteren Host bekommt der Agent also einen sauberen terminalen Fehler statt eines stillen Fehlschlags.
- 6.5 legt außerdem die Grundlage für eine eigene *VM-Administrator*-Rolle. Darauf muss man nicht warten: Die DADL exponiert die volle RBAC-v2-Oberfläche (`create_acl_role`, `create_acl_privilege`, `attach_acl_role_to_user`), sodass man heute schon eine least-privilege Operator-Rolle zusammenstellen und einem Agenten genau die Privilegien geben kann, die er haben soll — read auf `vm`, `host`, `pool`, mehr nicht.

Das allgemeine Argument haben wir [in einem früheren Post](/de/blog/dadl-the-end-of-mcp-server-boilerplate) gemacht; XO ist die konkrete Fallstudie für eine schreiblastige API.

## Das Context-Window-Argument

Es gibt einen zweiten Grund, warum die Tool-Zahl weniger zählt, als sie aussieht: **Code Mode**. Statt alle 245 XO-Tool-Beschreibungen in das Context-Window des Modells zu injizieren, exponiert ToolMesh zwei Meta-Tools (`list_tools` und `execute_code`). Das Modell entdeckt bei Bedarf, was verfügbar ist, und ruft flache Tool-Namen aus einer gesandboxten JavaScript-Runtime auf — `toolmesh.xen_orchestra_list_vms`, `toolmesh.xen_orchestra_snapshot_vm`, keinen verschachtelten Namespace.

Die Token-Kosten sind ungefähr konstant: ~1 k Tokens Meta-Tool-Beschreibung, egal ob die Registry ein Backend mit 7 Tools hält oder {{registry.apis}} Backends mit {{registry.tools}}. Ein 245-Tool-Backend fügt jeder Claude-Konversation, die Xen Orchestra nicht aktiv anfasst, null Tokens hinzu. Das ist auch der Grund, warum das JavaScript im Beispiel oben keine Illustration ist — es ist buchstäblich das, was das Modell schreibt, um die Tools aufzurufen.

## Ehrliche Einschränkungen

Die DADL ist kein universeller Gewinn. Echte Grenzen:

- **Der SSE-Event-Stream ist halb deklarativ.** `open_events_stream` gibt eine Subscription-ID zurück, und die DADL beschreibt den Subscribe-Handshake, aber der Server-Sent-Events-Stream selbst ist ein Streaming-Protokoll — DADL beschreibt REST, keine langlebigen Streams. Für das Pollen von Task-Status pollt `get_task?wait=true` sauber; für einen echten Echtzeit-Feed ist man am Rand dessen, was eine deklarative REST-Definition modelliert.
- **VDIs lassen sich nicht über REST umbenennen.** Es gibt kein `PATCH /vdis/{id}` in der API — also auch kein `update_vdi`-Tool. Umbenennen geht über Tags oder den Abstieg zur JSON-RPC-API. Wir exponieren, was existiert; wir können nicht exponieren, was es nicht gibt.
- **SDN-Traffic-Rules brauchen ein Premium-Plugin.** Die vier Traffic-Rule-Tools (`add`/`delete_network_traffic_rule`, `add`/`delete_vif_traffic_rule`) steuern den SDN-Controller von XO — ein Plugin, das XOA Premium beiliegt und nicht Teil der dokumentierten Kern-REST-API ist. Ohne geladenes Plugin liefern die Routen `404`, der Agent bekommt also einen sauberen terminalen Fehler statt eines stillen No-ops. Die übrigen 241 Tools laufen gegen eine Standard-REST-API.
- **Die Schreibseite braucht Privilegien.** Vollständige Coverage setzt einen Admin-User oder einen RBAC-v2-User mit den richtigen `acl-privileges` voraus. Wenn man nur *schauen* will, ist der read-only-Server von Vates weniger Setup und ein kleinerer Blast-Radius — nimm ihn.
- **Jeder Call hüpft durch ToolMesh.** Für interaktiven Betrieb ist das unsichtbar; für High-Throughput-Batch-Jobs gegen XO ist der direkte REST-Aufruf schneller.

DADL ist gut in einer bestimmten Sache — eine REST-API-Oberfläche schnell für Agenten verfügbar zu machen, mit einer echten Kontrollschicht darunter. Bei Xen Orchestra ist diese Oberfläche zufällig 245 Endpoints überwiegend verändernder Operationen — genau der Fall, in dem sich eine Governance-Schicht auszahlt.

## Was tatsächlich anders ist

Die substanzielle Frage ist nicht "DADL vs. der eigene MCP-Server" — ToolMesh betreibt beide, und sie koexistieren in derselben Registry. Die Frage ist: **Was kostet es, einem Agenten die *Schreib*-Seite einer API zu geben, sicher?**

Bei einem read-only-Server lautet die Antwort "gar nicht" — das ist der bewusste Trade. Bei einem handgeschriebenen Read-Write-Server kostet es einen Engineering-Zyklus pro Endpoint: SDK-Shapes, Handler, Tests, ein Release, ein npm-Publish, Nutzer-Upgrades, plus die Autorisierung und das Audit, die man selbst bauen muss. Bei einer DADL hinter ToolMesh kostet es einen PR mit einem YAML-Diff, und Credentials, Autorisierung und Audit kommen aus der Runtime.

Das ist die Asymmetrie. Nicht "alle sollten den eigenen Server wegwerfen" — behalte ihn für read-only-Discovery. Nur: wenn ein Agent Xen Orchestra tatsächlich betreiben soll, ist die Arbeitseinheit ein YAML-Diff, und die Sicherheit liegt in der Schicht darunter statt im Weglassen der Schreib-Tools.
