# Eigenen Connector bauen

> Den eigenen MCP-Server anbinden, aus einer OpenAPI-Beschreibung oder ein paar REST-Aufrufen einen Connector machen oder einen Skill importieren. Bei selbst betriebenen Installationen einen Connector als Manifest ausliefern. Mit der vollständigen Manifest-Referenz.

Der Katalog deckt die verbreiteten Systeme ab. Jedes Unternehmen hat aber auch eigene: einen hausinternen Servicedesk, einen Maschinendaten-Server vom IoT-Anbieter, feste Regeln für Angebote. Diese binden Sie selbst an, ohne auf ein Release zu warten, und sie werden behandelt wie Katalog-Connectoren: Rechteprüfung bei jedem Aufruf, Bestätigung vor dem Schreiben, Schlüssel, die auf dem Server bleiben.

Brandt & Söhne macht beides. Ihr IoT-Anbieter betreibt einen MCP-Server für Maschinendaten, den Mia Schulz aus der Fertigung per Adresse anbindet und mit der Rolle „Fertigung“ teilt. Ihr Servicedesk hat eine REST-Schnittstelle mit OpenAPI-Beschreibung, die Tom Keller in fünf Minuten importiert und dabei nur die Operationen auswählt, die der KI-Assistent haben soll.

## Den passenden Weg wählen

| Sie haben | Sie bauen | Wo Sie anfangen |
|---|---|---|
| Die Adresse eines entfernten MCP-Servers oder einen Konfigurationsblock aus Claude Desktop, Cursor, opencode oder VS Code | Einen MCP-Connector | <Ui>Neu</Ui> › <Ui>MCP-Connector</Ui> oder <Ui>JSON einfügen</Ui> |
| Eine Schnittstelle mit OpenAPI-3- oder Swagger-2-Beschreibung | Einen Connector aus OpenAPI | <Ui>Neu</Ui> › <Ui>Aus OpenAPI</Ui> |
| Eine Schnittstelle mit Dokumentation, aber ohne Beschreibungsdatei | Einen Connector aus REST-Aktionen | <Ui>Neu</Ui> › <Ui>REST-Aktionen</Ui> |
| Eine wiederkehrende Aufgabe, die sich in Worten beschreiben lässt | Einen Skill | <Ui>Neu</Ui> › <Ui>Skill importieren</Ui> |
| Eine selbst betriebene Installation und einen Connector für jeden Mandanten | Ein Manifest, das mit dem Build ausgeliefert wird | [Connector als Manifest ausliefern](#connector-als-manifest-ausliefern) |

Alle vier beginnen unter <MenuPath to="KI > KI einrichten > Connectoren" />: Der Knopf <Ui>Neu</Ui> in der Aktionsleiste öffnet das Menü. Was Sie bauen, erscheint im Reiter <Ui>Meine Connectoren</Ui> und für alle, mit denen Sie es teilen, im Connector-Menü des Chats.

<Screenshot src={shot_plg_catalog_new} url="/plugins" alt={"Das Menü Neu auf der Connector-Seite mit fünf Wegen, einen Connector zu bauen"} caption={"Jeder eigene Connector beginnt im Menü Neu."} />

## Bevor Sie beginnen

- Sie brauchen das Recht `ai.plugin.create`. Um mit anderen zu teilen, brauchen Sie zusätzlich `ai.plugin.share`.
- Der Server oder die Schnittstelle muss **vom nexxus-Server aus** erreichbar sein, nicht nur von Ihrem Rechner. Jeder Aufruf kommt von dort, auch der Verbindungstest.
- Ein Ziel im Firmennetz braucht eine Freigabe unter <Ui>Netz-Freigabe</Ui>. Die richtet ein Administrator ein, siehe [Systeme im eigenen Netz erreichen](/de/plugins/set-up/#systeme-im-eigenen-netz-erreichen).

## Einen MCP-Server anbinden

MCP (Model Context Protocol) ist ein Standard, mit dem ein Server einer KI Werkzeuge anbietet. Betreibt ein Anbieter oder Ihr eigenes Team einen MCP-Server, kann nexxus dessen Werkzeuge direkt nutzen. nexxus spricht mit entfernten Servern über **Streamable HTTP** oder das ältere **SSE**. Lokale Server, die als Programm auf einem Rechner laufen (`command` und `args` in einer Konfiguration), werden nicht unterstützt, weil nexxus auf seinem Server keine fremden Prozesse startet.

### Connector anlegen

<Steps>

1. Klicken Sie unter <MenuPath to="KI > KI einrichten > Connectoren" /> auf <Ui>Neu</Ui> › <Ui>MCP-Connector</Ui>. Die Seite <Ui>Neuer MCP-Connector</Ui> öffnet sich im Reiter <Ui>Formular</Ui>.

2. Füllen Sie <Ui>Server</Ui> aus:

   - <Ui>Name</Ui>: So erscheint der Connector in der Auswahl, höchstens 120 Zeichen.
   - <Ui>Adresse</Ui>: die MCP-Adresse, meist auf `/mcp` oder `/sse` endend. Sie muss mit `http://` oder `https://` beginnen.
   - <Ui>Beschreibung</Ui>: wofür er da ist. Der KI-Assistent liest sie mit.
   - <Ui>Transport</Ui>: <Ui>Streamable HTTP</Ui> oder <Ui>SSE (ältere Server)</Ui>.
   - <Ui>Kürzel</Ui>: die Vorsilbe der Werkzeugnamen, Kleinbuchstaben, Ziffern und Bindestriche, höchstens 40 Zeichen. Leer heißt: aus dem Namen gebildet.
   - <Ui>Anmeldung</Ui>: <Ui>Keine</Ui>, <Ui>Header (z. B. API-Schlüssel)</Ui> oder <Ui>OAuth (dynamische Registrierung)</Ui>. Siehe [Anmeldearten](#anmeldearten).

3. Klicken Sie auf <Ui>Anlegen</Ui>. nexxus speichert den Connector und testet ihn sofort. Das Speichern scheitert nie daran, dass der Server nicht geantwortet hat: Der Connector behält das Ergebnis und zeigt es an.

</Steps>

<Screenshot src={shot_plg_connector_form} url="/plugins/connectors/new" alt={"Das Formular für einen neuen MCP-Connector mit Zugangsdaten pro Person"} caption={"Ein Connector braucht einen Namen, eine Adresse und die Anmeldeart."} />

### Stattdessen eine Konfiguration einfügen

Viele MCP-Server bringen einen Konfigurationsblock für KI-Desktop-Programme mit. Fügen Sie ihn unverändert ein: <Ui>Neu</Ui> › <Ui>JSON einfügen</Ui>, dann <Ui>Einlesen</Ui>.

```json
{
  "mcpServers": {
    "maschinendaten": {
      "url": "https://mcp.iot-vendor.example/mcp",
      "headers": { "Authorization": "Bearer replace-with-your-token" }
    },
    "local-files": {
      "command": "npx",
      "args": ["some-local-mcp-server"]
    }
  }
}
```

nexxus zeigt <Ui>Ein Connector erkannt</Ui> für `maschinendaten`, markiert <Ui>mit Headern</Ui>, und <Ui>Ein Eintrag abgelehnt</Ui> für `local-files` mit dem Grund <Ui>Lokaler Server (command/args): der läuft auf Ihrem Rechner, nicht auf unserem Server, und fremde Prozesse starten wir dort nicht.</Ui> Zu jedem erkannten Eintrag klicken Sie auf <Ui>Im Formular prüfen</Ui> oder direkt auf <Ui>Anlegen</Ui>. Gespeichert wird erst, wenn Sie es sagen.

nexxus versteht die Formate von Claude Desktop und Cursor (`mcpServers`), opencode (`mcp` mit `type: remote`) und VS Code (`servers`), einzelne Einträge, Listen von Einträgen und nackte `"name": {...}`-Stücke, die aus einer größeren Datei kopiert wurden. Kommentare, Kommas am Ende und einfache Anführungszeichen stören nicht. Ein Einfügen kann bis zu 50 Einträge enthalten. Eine Adresse, die noch eine Vorlage ist, etwa `http://IP:PORT/mcp`, lehnt nexxus ab: <Ui>Die Adresse ist ein Platzhalter (z. B. IP:PORT). Bitte die echte Adresse eintragen.</Ui>

<Screenshot src={shot_plg_connector_json} url="/plugins/connectors/new?mode=json" alt={"Eine eingefügte MCP-Konfiguration mit einem erkannten Connector und einem abgelehnten Eintrag"} caption={"Lokale Server werden abgelehnt, weil nexxus keine fremden Prozesse startet."} />

### Anmeldearten

| <Ui>Anmeldung</Ui> | <Ui>Zugangsdaten</Ui> | So funktioniert es |
|---|---|---|
| <Ui>Keine</Ui> | | Der Server braucht keinen Schlüssel. |
| <Ui>Header (z. B. API-Schlüssel)</Ui> | <Ui>Geteilt: alle nutzen den hinterlegten Schlüssel</Ui> | Sie tragen Header-Name und Wert einmal ein (<Ui>Header hinzufügen</Ui>, bis zu 30). Alle, die den Connector benutzen, arbeiten mit diesem Schlüssel. |
| <Ui>Header (z. B. API-Schlüssel)</Ui> | <Ui>Pro Person: jede Person hinterlegt eigene</Ui> | Sie nennen die Header-Namen unter <Ui>Header, die jede Person selbst ausfüllt</Ui>, durch Komma getrennt, etwa `Authorization`. Jede Person trägt ihre eigenen Werte unter <Ui>Meine Zugangsdaten</Ui> oder beim Verbinden ein. Feste Header für alle können daneben stehen. |
| <Ui>OAuth (dynamische Registrierung)</Ui> | | Jede Person meldet sich beim ersten Benutzen selbst beim Server an. nexxus registriert sich dort selbst als Client, eine App müssen Sie nicht einrichten. |

Header-Werte werden verschlüsselt gespeichert und nie wieder angezeigt. Header, die die Verbindung selbst setzt, etwa den Inhaltstyp, können Sie nicht überschreiben. Nutzt die Adresse unverschlüsseltes `http://`, warnt das Formular: <Ui>Die Adresse ist unverschlüsseltes http://. Schlüssel gehen so nur an Ziele, die ein Admin in der Netz-Freigabe eingetragen hat.</Ui>

Lehnt der Server die dynamische Registrierung ab, sagt der Fehlerdialog <Ui>{'{name} lässt keine automatische Anmeldung zu'}</Ui>. Stellen Sie den Connector auf Header um, wenn der Server auch einen API-Schlüssel annimmt, oder bitten Sie den Betreiber, die dynamische Client-Registrierung freizuschalten.

### Verbindung testen

Klicken Sie unter <Ui>Verbindung testen</Ui> auf <Ui>Verbindung testen</Ui>. Der Test läuft vom Server aus, also von dort, wo später auch die echten Aufrufe herkommen, und durchläuft sechs Stufen: <Ui>DNS</Ui>, <Ui>Verbinden</Ui>, <Ui>TLS</Ui>, <Ui>HTTP</Ui>, <Ui>MCP-Start</Ui> und <Ui>Werkzeugliste</Ui>. Das Ergebnis ist <Ui>Verbindung steht</Ui> oder <Ui>Verbindung fehlgeschlagen</Ui> mit der gescheiterten Stufe, dazu <Ui>Server</Ui>, <Ui>Protokoll</Ui>, <Ui>Verschlüsselt</Ui>, <Ui>Antwortzeit</Ui> und die Zahl der <Ui>Werkzeuge</Ui>. Sie können schon vor dem Speichern testen: nexxus nimmt die Werte aus dem Formular, und für leer gelassene Header-Felder die gespeicherten Werte.

<Screenshot src={shot_plg_connector_test} url="/plugins/connectors/1" alt={"Ein erfolgreicher Verbindungstest und die Werkzeugliste eines Connectors"} caption={"Der Test läuft vom Server aus und holt die Werkzeugliste."} />

### Werkzeuge auswählen

<Ui>Werkzeuge</Ui> listet, was der Server anbietet, mit einem Häkchen je Werkzeug (<Ui>{'{tool} benutzen'}</Ui>) und der Wahl <Ui>Lesen</Ui> oder <Ui>Schreiben</Ui>. Ein Werkzeug gilt nur dann als lesend, wenn der Server es als nur lesend kennzeichnet. Alles andere gilt als schreibend, und schreibende Werkzeuge fragen vor jedem Aufruf nach.

- Ist der Connector mit niemandem geteilt (<Ui>Nur ich</Ui>), können Sie die Bestätigung für ein schreibendes Werkzeug abschalten: <Ui>Aus: dieses Werkzeug schreibt ohne Karte. Nur solange der Connector nur Ihnen gehört.</Ui> Sobald Sie ihn teilen, fragen schreibende Werkzeuge wieder.
- <Ui>Ausprobieren</Ui> öffnet <Ui>{'{tool} ausprobieren'}</Ui>: ein Formular, das aus der Eingabebeschreibung des Werkzeugs entsteht, und <Ui>Aufrufen</Ui>, das einen echten Aufruf macht (höchstens 30 Sekunden) und das Ergebnis als JSON zeigt. Ausprobieren dürfen Besitzer und Mitverwaltende. Es geht nach dem Speichern.

Ist die Liste leer, steht dort <Ui>Noch keine Werkzeuge bekannt. „Verbindung testen“ holt die Liste vom Server.</Ui>

<Screenshot src={shot_plg_dlg_tooltry} url="/plugins/connectors/1" alt={"Ein Werkzeug eines Connectors ausprobieren"} caption={"Ausprobieren macht einen echten Aufruf und zeigt das Ergebnis so, wie der Assistent es bekäme."} />

### Teilen

<Ui>Freigabe</Ui> legt fest, wer den Connector benutzen darf. Wer es nicht darf, sieht ihn auch nicht.

| Option | Wer ihn benutzen darf |
|---|---|
| <Ui>Nur ich</Ui> | Nur Sie und die Mitverwaltenden |
| <Ui>Bestimmte Personen</Ui> | Die Personen, die Sie auswählen |
| <Ui>Rollen</Ui> | Alle mit einer der Rollen |
| <Ui>Geschäftseinheit</Ui> | Alle in der Einheit und darunter |
| <Ui>Ganze Firma</Ui> | Alle in diesem Mandanten |

Jede Option außer <Ui>Nur ich</Ui> braucht das Recht `ai.plugin.share`. Ohne es sind die Optionen gesperrt: <Ui>Zum Teilen brauchen Sie das Recht „Mit anderen teilen“.</Ui> Teilen Sie einen Connector mit geteiltem Schlüssel, warnt das Formular: <Ui>Alle, mit denen Sie teilen, arbeiten mit Ihrem Schlüssel und damit mit Ihren Rechten beim Anbieter.</Ui> Wollen Sie das nicht, nehmen Sie Zugangsdaten pro Person.

Unter den Freigabe-Optionen:

- <Ui>Mitverwaltende</Ui> dürfen Einstellungen und Freigabe ändern, aber nicht löschen oder übertragen.
- <Ui>Connector</Ui> <Ui>An</Ui> oder <Ui>Aus</Ui>: Ausgeschaltet verschwindet er bei allen aus der Auswahl, die Daten bleiben.
- <Ui>In neuen Unterhaltungen vorausgewählt</Ui>: Wer ihn benutzen darf, hat ihn in neuen Unterhaltungen gleich angehakt.
- <Ui>Vor der ersten Benutzung fragen</Ui> (standardmäßig an): Daten verlassen diese Installation, deshalb stimmt die Person einmal je Unterhaltung vor dem ersten Aufruf zu.

Dieselben Freigabe-Optionen gelten für Connectoren aus OpenAPI, aus REST-Aktionen und für importierte Skills.

<Screenshot src={shot_plg_connector_sharing} url="/plugins/connectors/1" alt={"Die Freigabe-Optionen eines Connectors"} caption={"Wer den Connector benutzen darf und ob die erste Benutzung je Unterhaltung nachfragt."} />

### Im Betrieb

- **Prüfung alle 15 Minuten.** nexxus testet jeden eingeschalteten Connector so, wie sein Besitzer ihn aufrufen würde, und frischt dabei die Werkzeugliste auf. Fällt ein Connector aus, der funktioniert hat, bekommt der Besitzer einmal je Ausfall einen Hinweis in der Glocke und per E-Mail. Das stellt jeder Besitzer unter <MenuPath to="Mein Profil > Benachrichtigungen" /> ein, Abschnitt <Ui>Eigene MCP-Connectoren nicht erreichbar</Ui>.
- **Auf einen anderen Server umstellen.** Die Adresse auf einen anderen Server umstellen dürfen nur der Besitzer oder ein Connector-Admin. Gespeicherte Header-Werte werden nicht mitgenommen, und die eigenen Zugangsdaten und Anmeldungen aller Personen für diesen Connector werden verworfen. Wer ihn benutzt, verbindet sich danach neu.
- **Erweitert.** <Ui>Zeitlimit (ms)</Ui> zwischen 1 000 und 120 000 für langsame Server. <Ui>Eigenes CA-Zertifikat (PEM)</Ui> für Server mit Zertifikat einer firmeneigenen Zertifizierungsstelle.
- **Besitz übertragen.** Wählen Sie unter <Ui>Besitz übertragen</Ui> eine Person, die Connectoren anlegen darf, und klicken Sie auf <Ui>Übertragen</Ui>. Sie bleiben Mitverwaltende, verlieren aber das Recht zu löschen und zu übertragen.
- **Wenn der Besitzer geht.** Ein eigener Connector, dessen Besitzer gelöscht wurde, dessen Einladung noch offen ist oder der zum Dienstkonto wurde, geht an den ersten Administrator des Mandanten. Gelöscht wird er nie, weil andere ihn benutzen könnten.
- **Grenzen.** Jede Person kann bis zu 50 Connectoren besitzen, Administratoren unbegrenzt viele.

## Einen Connector aus einer OpenAPI-Beschreibung bauen

Eine OpenAPI-Beschreibung listet jede Operation einer Schnittstelle mit ihren Parametern. nexxus macht aus den Operationen, die Sie auswählen, Aktionen.

<Steps>

1. Klicken Sie auf <Ui>Neu</Ui> › <Ui>Aus OpenAPI</Ui>. Die Seite <Ui>Connector aus OpenAPI</Ui> öffnet sich.

2. Wählen Sie unter <Ui>Spezifikation</Ui> <Ui>Adresse</Ui> und tragen Sie die URL der Beschreibung ein (etwa `https://servicedesk.brandt.example/openapi.json`), oder wählen Sie <Ui>Einfügen</Ui> und fügen Sie sie ein. JSON und YAML gehen beide. Zeigt die Schnittstelle ihre Beschreibung nur angemeldeten Aufrufern, wählen Sie unter <Ui>Zugang zur Adresse</Ui> <Ui>Token</Ui> oder <Ui>Benutzername und Passwort</Ui> und tragen Sie die Zugangsdaten ein. Klicken Sie auf <Ui>Einlesen</Ui>.

3. Wählen Sie unter <Ui>Operationen</Ui>, was der KI-Assistent tun darf. Jede ausgewählte Operation wird eine Aktion. Lesende Operationen (GET) sind vorausgewählt, alle anderen gelten als schreibend und fragen vor jedem Aufruf nach. <Ui>{'Alle ({count} von {total})'}</Ui> wählt alle aus oder ab.

4. Prüfen Sie unter <Ui>Name und Beschreibung</Ui> den Namen und beschreiben Sie in einem Satz, wofür der Connector gut ist. Der KI-Assistent liest die Beschreibung.

5. Legen Sie die <Ui>Freigabe</Ui> fest und klicken Sie auf <Ui>Anlegen</Ui>. nexxus öffnet die Seite des neuen Connectors.

</Steps>

<Screenshot src={shot_plg_def_openapi} url="/plugins/definitions/new?source=openapi" alt={"Operationen aus einer OpenAPI-Beschreibung importieren"} caption={"Jede ausgewählte Operation wird eine Aktion. Lesende sind vorausgewählt."} />

Was nexxus aus der Beschreibung übernimmt:

| Aus der Beschreibung | Wird zu |
|---|---|
| `servers[0]` | Die Basis-URL. Gibt es keine, fragt nexxus danach. |
| Jede ausgewählte Operation | Eine Aktion. GET liest, POST, PUT, PATCH und DELETE schreiben. |
| Pfad-, Query- und Header-Parameter, ein JSON-Body | Die Eingaben der Aktion |
| Security Schemes | Die Anmeldung, mit den Feldern, die jede Person beim Verbinden ausfüllt. Stehen mehrere zur Wahl, nimmt nexxus die, die die meisten Operationen verlangen. |

Nicht übernommen werden Verweise auf andere Dateien, Callbacks, formularkodierte Bodies und Cookie-Parameter. Die Beschreibung darf bis zu 5 MB groß sein. Unterstützt werden OpenAPI 3.0, 3.1 und Swagger 2.0. Eine eingefügte Beschreibung wird nicht gespeichert: Um die Operationen später zu ändern, fügen Sie sie erneut ein und lesen sie ein.

Den <Ui>Zugang zur Adresse</Ui> sendet nexxus nur beim Einlesen der Beschreibung, nie mit den Aufrufen der Aktionen. Er wird verschlüsselt gespeichert und nicht wieder angezeigt; ein leeres Feld behält den gespeicherten Wert. Ziehen Sie die Adresse auf einen anderen Server um, verwirft nexxus ihn. Wie sich jede Person bei der Schnittstelle selbst anmeldet, legen davon getrennt die Security Schemes fest.

## Einen Connector aus REST-Aktionen bauen

Hat eine Schnittstelle Dokumentation, aber keine Beschreibungsdatei, beschreiben Sie die Aufrufe selbst. Eine Handvoll gut beschriebener Aktionen hilft dem KI-Assistenten oft mehr als ein vollständiger Import.

<Steps>

1. Klicken Sie auf <Ui>Neu</Ui> › <Ui>REST-Aktionen</Ui>. Die Seite <Ui>Connector aus REST-Aktionen</Ui> öffnet sich.

2. Tragen Sie unter <Ui>Schnittstelle</Ui> die <Ui>Basis-URL</Ui> ein (etwa `https://servicedesk.brandt.example/api/v1`) und wählen Sie die <Ui>Anmeldung</Ui>: <Ui>Keine</Ui>, <Ui>API-Schlüssel</Ui> oder <Ui>Benutzername und Passwort</Ui>. Mit Schlüssel oder Login hinterlegt jede Person beim Verbinden ihre eigenen Zugangsdaten.

   Beim API-Schlüssel wählen Sie unter <Ui>Schlüssel senden als</Ui>, wie die Schnittstelle ihn erwartet: <Ui>Bearer-Token (Authorization-Header)</Ui>, <Ui>Eigener Header</Ui> oder <Ui>Parameter in der Adresse</Ui>. Für die beiden letzten tragen Sie den <Ui>Name des Headers oder Parameters</Ui> aus der Doku der Schnittstelle ein, bei Pipedrive etwa `x-api-token`. Lehnt die Schnittstelle den Schlüssel ab, sagt der KI-Assistent das mit dem Grund des Anbieters, etwa `Pipedrive hat die Zugangsdaten abgelehnt (401): unauthorized access.` Stimmt der Schlüssel, steht meist <Ui>Schlüssel senden als</Ui> falsch.

3. Beschreiben Sie unter <Ui>Aktionen</Ui> jeden Aufruf:

   - <Ui>Methode</Ui> (GET, POST, PUT, PATCH, DELETE) und <Ui>Pfad</Ui>, etwa `/tickets/{id}`. Platzhalter in geschweiften Klammern brauchen eine Eingabe mit demselben Namen.
   - <Ui>Lesen</Ui> oder <Ui>Schreiben</Ui>. Schreibende Aktionen fragen immer vorher nach.
   - <Ui>Schlüssel (z. B. search_deals)</Ui>: Kleinbuchstaben, Ziffern und Unterstriche, mit einem Buchstaben am Anfang. Er wird Teil des Werkzeugnamens.
   - <Ui>Name</Ui> und <Ui>Was die Aktion tut und was sie zurückgibt</Ui>. Die Beschreibung entscheidet, ob der KI-Assistent die Aktion richtig benutzt. Schreiben Sie, wofür sie da ist und was zurückkommt.
   - Eingaben mit <Ui>Eingabe hinzufügen</Ui>: <Ui>Eingabe</Ui> (Name), <Ui>Typ</Ui> (string, integer, number, boolean, array, object), <Ui>Ort</Ui> (<Ui>Query</Ui>, <Ui>Pfad</Ui>, <Ui>Body</Ui>, <Ui>Header</Ui>), <Ui>Pflicht</Ui> und <Ui>Beschreibung</Ui>.

   Weitere Aufrufe fügen Sie mit <Ui>Aktion hinzufügen</Ui> an.

4. Füllen Sie <Ui>Name und Beschreibung</Ui> und <Ui>Freigabe</Ui> aus und klicken Sie auf <Ui>Anlegen</Ui>.

</Steps>

<Screenshot src={shot_plg_def_rest} url="/plugins/definitions/new?source=rest" alt={"REST-Aktionen für einen Connector beschreiben"} caption={"Die Beschreibung entscheidet, ob der Assistent die Aktion richtig benutzt."} />

Für den Servicedesk reichen für den Anfang zwei Aktionen:

| Schlüssel | Methode und Pfad | Art | Eingaben |
|---|---|---|---|
| `search_tickets` | `GET /tickets` | Lesen | `q` (string, Query, Pflicht): Suchtext |
| `create_ticket` | `POST /tickets` | Schreiben | `subject` (string, Body, Pflicht), `body` (string, Body, Pflicht) |

### Regeln für eigene Connectoren

Sie gelten für Connectoren aus OpenAPI und aus REST-Aktionen gleichermaßen.

- **Sie laufen wie Katalog-Connectoren.** nexxus prüft sie nach denselben Regeln wie die Connectoren, die es mitliefert: eine Basis-URL mit `https://` (oder ein Wert aus der Konfiguration), Bestätigung für jede schreibende Aktion, Werkzeugnamen mit höchstens 64 Zeichen.
- **Ihre Verbindungen gehören nur ihnen.** Ein selbst gebauter Connector bekommt immer eigene Verbindungen. Er kann nie den Token eines Katalog-Connectors bekommen, auch wenn er denselben Anbieter beschreibt.
- **Die Adresse entscheidet der Besitzer.** Verschiebt eine Änderung eine Adresse des Connectors auf einen anderen Server, dürfen nur der Besitzer oder ein Connector-Admin speichern. Gespeicherte Geheimnisse für die alte Adresse fallen weg, und jede Verbindung wird widerrufen mit dem Hinweis `Die Adresse des Connectors hat sich geändert. Bitte neu verbinden.`
- **Die Basis-URL wird beim Speichern geprüft.** Sperren die Netzregeln eine feste Basis-URL, lehnt nexxus das Speichern ab. So erfahren Sie es, bevor jemand es im Chat versucht.

## Einen Skill importieren

Ein Skill ist schriftliches Wissen: die Schritte und Regeln für eine wiederkehrende Aufgabe, in Markdown. Er kann die Connectoren nennen, die er braucht, und wer den Skill in einer Unterhaltung einschaltet, schaltet diese mit ein. Solange der Skill an ist, gehen seine Anweisungen mit jeder Nachricht mit.

Ein Skill ist eine Datei `SKILL.md` mit einem kurzen Frontmatter. So sieht der aus, den nexxus zum Glätten von Texten mitliefert (gekürzt):

```markdown
---
name: text-glaetten
description: Glättet einen Text sprachlich, ohne Ton und Aussage zu verändern, zum Beispiel ein diktiertes Transkript.
---

# Text glätten (Lektor)

Ziel: der Text liest sich flüssig und fehlerfrei, klingt aber weiter nach der Person, die ihn geschrieben oder diktiert hat.

Korrigieren:

- Rechtschreibung, Grammatik, Zeichensetzung, Groß- und Kleinschreibung
- Füllwörter, Wiederholungen und abgebrochene Sätze aus gesprochener Sprache
```

Das Frontmatter nimmt `name`, `slug` und `description`. Ein Skill mit zusätzlichen Dateien (Vorlagen, Beispiele) kommt als ZIP, mit der `SKILL.md` an der Wurzel oder in einem Ordner:

<FileTree>
- angebot-wartung.zip
  - angebot-wartung
    - SKILL.md
    - vorlage-wartungsvertrag.md
    - beispiele/
</FileTree>

<Steps>

1. Klicken Sie auf <Ui>Neu</Ui> › <Ui>Skill importieren</Ui>.

2. Klicken Sie unter <Ui>Skill-Datei</Ui> auf <Ui>Datei auswählen</Ui> und wählen Sie die `.md`- oder `.zip`-Datei.

3. Haken Sie unter <Ui>Benötigte Integrationen</Ui> die installierten Connectoren an, die der Skill braucht. Sie werden eingeschaltet, sobald der Skill in einer Unterhaltung benutzt wird.

4. Legen Sie die <Ui>Freigabe</Ui> fest und klicken Sie auf <Ui>Importieren</Ui>.

</Steps>

<Screenshot src={shot_plg_def_skill} url="/plugins/definitions/new?source=skill" alt={"Einen Skill mit seinen benötigten Integrationen importieren"} caption={"Benötigte Integrationen werden eingeschaltet, sobald der Skill benutzt wird."} />

Ein ZIP darf bis zu 2 000 Dateien enthalten, jede höchstens 25 MB, entpackt zusammen höchstens 100 MB. Ein Skill kann bis zu 20 benötigte Connectoren nennen. Die Anweisungen ändern Sie, indem Sie die Datei erneut importieren, oder über <Ui>Skill öffnen</Ui>. Am Connector selbst ändern Sie Freigabe, An und Aus und die benötigten Connectoren.

## Connector als Manifest ausliefern

Bei einer selbst betriebenen Installation können Entwickler einen Connector direkt in den Katalog aufnehmen, für jeden Mandanten. Ein Katalog-Connector ist ein Ordner mit Manifest und Symbol in den Ressourcen des Backends:

<FileTree>
- backend/src/main/resources/plugins/
  - servicedesk/
    - plugin.yml das Manifest
    - icon.svg oder icon.png, Pflicht
    - SKILL.md nur bei Skills
</FileTree>

nexxus liest beim Start jede `plugins/<key>/plugin.yml`. Der Ordnername muss dem `key` des Manifests entsprechen. Ein Manifest, das sich nicht lesen oder nicht prüfen lässt, lässt nexxus mit einem Fehler im Log weg (`Plugin-Manifest plugins/<Ordner>/plugin.yml wird ignoriert: ...`). Eine kaputte Datei hält so nie den Server auf. Die Tests des Builds lehnen sie ab, bevor sie ausgeliefert wird. Danach installiert ein Administrator den Connector wie jeden anderen.

### Ein minimales Manifest

Das ist der Perplexity-Connector, wie er ausgeliefert wird, gekürzt auf eine seiner sechs Aktionen. Er meldet sich mit einem API-Schlüssel an, den jede Person oder ein Administrator einträgt, ruft eine REST-Schnittstelle auf und kürzt die Antwort auf die Felder, die der KI-Assistent braucht.

```yaml
schema: 1
key: perplexity
kind: integration
status: available
name: Perplexity
description: Websuche mit Quellenangaben, schnelle Antworten und ausführliche Recherchen über die Perplexity-API.
category: media_ai
vendor: Perplexity
docsUrl: https://docs.perplexity.ai/api-reference/agent-post
dataFlow: Anfragen gehen mit dem API-Schlüssel direkt an die Perplexity-API (api.perplexity.ai); jede Anfrage wird dem Perplexity-API-Projekt berechnet.
tags: [perplexity, websuche, web search, recherche, research, quellen]
auth:
  provider: perplexity
  type: api_key
  scope: user_or_tenant
  inject:
    in: header
    name: Authorization
    value: "Bearer {connection.token}"
runtime:
  type: rest
  baseUrl: https://api.perplexity.ai
  helper: none
defaultActive: false
toggleable: true
connectionFields:
  - { key: token, label: "Perplexity-API-Schlüssel", type: password, required: true, description: "Schlüssel von der Seite „API Keys“ in der Perplexity API Console" }
actions:
  - key: search_web
    name: Web durchsuchen
    description: >-
      Durchsucht das Web und liefert eine Trefferliste mit Titel, URL, Textauszug (snippet) und Datum, ohne eigene Antwort.
      Verwenden, wenn Quellen, Links oder aktuelle Fundstellen gebraucht werden. Für eine formulierte Antwort ask verwenden.
    kind: read
    confirm: never
    method: POST
    path: /search
    input:
      - { name: query, type: string, required: true, location: body, description: "Suchanfrage" }
      - { name: max_results, type: integer, location: body, default: 10, min: 1, max: 20, description: "Anzahl Treffer" }
    output:
      pick: ["results[].title", "results[].url", "results[].snippet", "results[].date", "results[].last_updated"]
i18n:
  en:
    name: Perplexity
    description: "Web search with citations, quick answers and in-depth research through the Perplexity API."
```

Das Manifest selbst ist deutsch. Englisch steht unter `i18n.en`, und die englische Oberfläche zeigt es. Die Aktion wird zum Werkzeug `perplexity__search_web`: der Connector-Schlüssel mit `_` statt `-`, zwei Unterstriche, der Aktionsschlüssel.

### Manifest-Referenz

Unbekannte Felder lehnt nexxus ab. Ein vertipptes Feld scheitert also, statt still nichts zu tun. nexxus meldet alle Probleme auf einmal.

#### Oberste Ebene

| Feld | Typ | Pflicht | Bedeutung |
|---|---|---|---|
| `schema` | Zahl | ja | Immer `1` |
| `key` | Text | ja | `[a-z0-9-]`, 2 bis 63 Zeichen, gleich dem Ordnernamen |
| `kind` | `tool`, `integration`, `skill` | ja | Der Chip im Katalog |
| `name`, `description` | Text | ja | Deutsch. Anhand der Beschreibung entscheidet der KI-Assistent, ob der Connector passt. |
| `category` | Text | ja | `builtin`, `microsoft`, `google`, `communication`, `docs_knowledge`, `projects`, `dev`, `crm_sales`, `support`, `hr`, `finance`, `commerce`, `marketing`, `data`, `storage`, `design`, `automation`, `media_ai`, `systaro` oder `custom` |
| `vendor`, `docsUrl` | Text | nein | Auf der Connector-Seite, `docsUrl` als <Ui>Dokumentation</Ui> |
| `dataFlow` | Text | nein | Ein Satz dazu, wohin die Daten gehen, auf der Connector-Seite |
| `status` | `available`, `planned` | nein | Standard `available`. `planned` ist nur eine Karte im Katalog. |
| `statusHint` | Text | nein | Warum ein geplanter Connector noch fehlt |
| `tags` | Liste | nein | Suchwörter in Kleinbuchstaben |
| `popularSeed` | Zahl | nein | Reihenfolge unter <Ui>Beliebt</Ui>, solange noch niemand verbunden ist |
| `defaultActive` | ja/nein | nein | Nach der Installation in neuen Unterhaltungen vorausgewählt. Standard `false`. |
| `toggleable` | ja/nein | nein | `false` macht ihn zum Kern-Connector: in jeder Unterhaltung immer an. Standard `true`. |
| `adminOnly` | ja/nein | nein | Nur Administratoren sehen und benutzen ihn |
| `installByDefault` | ja/nein | nein | Für jeden Mandanten installiert, bis ein Administrator ihn deinstalliert. Nur für Werkzeuge und Skills ohne Anmeldung. |
| `auth` | Objekt | nein | Wie er sich anmeldet, siehe unten. Standard: keine Anmeldung. |
| `runtime` | Objekt | ja, außer bei Skills und geplanten Connectoren | Wie er läuft, siehe unten |
| `actions` | Liste | bei `rest` | Was der KI-Assistent tun kann, siehe unten |
| `triggers` | Liste | nein | Was einen KI-Schedule starten kann, siehe unten |
| `config` | Liste von Feldern | nein | Werte, die ein Administrator unter <Ui>Konfiguration</Ui> einträgt |
| `connectionFields` | Liste von Feldern | bei `api_key`, `basic` und `session` | Was jede Verbindung einträgt, etwa den API-Schlüssel |
| `instructions` | Text | Skills | Die Anweisungen, oder `SKILL.md` für eine Datei neben dem Manifest |
| `requires`, `requiresAny` | Liste von Connector-Schlüsseln | nein | Skills: alle aus `requires` werden gebraucht, mindestens eines aus `requiresAny` |
| `setup` | Objekt | nein | Hilfe auf der Connector-Seite: `admin` und `user` (Listen von Schritten), `links` (`label`, `url` mit https) |
| `permissions` | Liste | nein | Berechtigungsgruppen, nur bei OAuth-Connectoren, siehe unten |
| `i18n` | Objekt | nein | Übersetzungen nach zweibuchstabigem Sprachcode, etwa `en` mit `name`, `description`, `dataFlow`, `statusHint`, `setup`, `actions` und `permissions` |

#### `auth`

| Feld | Bedeutung |
|---|---|
| `type` | `none`, `api_key`, `basic`, `session` (ein Login-Formular, das mit einem Sitzungs-Cookie antwortet), `oauth2`, `oauth2_dcr` (OAuth mit dynamischer Client-Registrierung) oder `client_credentials` |
| `scope` | `user` (jede Person verbindet), `tenant` (eine Verbindung für alle) oder `user_or_tenant` (beides, die eigene gilt zuerst). Standard `user`. |
| `provider` | Der Schlüssel der Verbindung. Connectoren mit demselben Anbieter und derselben App teilen sich eine Anmeldung, etwa `microsoft`. Pflicht für jede Art außer `none` und `oauth2_dcr`. |
| `authorizeUrl`, `tokenUrl`, `revokeUrl` | OAuth-Endpunkte. `https://` oder am Anfang ein Wert aus der Konfiguration wie `{config.baseUrl}`. |
| `scopes` | Was die Anmeldung anfragt |
| `scopeSeparator` | Wie die Scopes verbunden werden. Standard ein Leerzeichen. |
| `pkce` | PKCE bei der Anmeldung. Standard `true`. |
| `authorizeParams` | Zusätzliche Parameter für die Anmeldung, etwa `access_type: offline` |
| `inject` | Wohin ein API-Schlüssel oder Login gehört: `{in: header, name, value}`, `{in: query, name, value}` oder `{in: basic, username, password}`. Werte nehmen `{connection.<Feld>}` und `{config.<Feld>}`. |
| `login` | Nur bei `session`: das Login-Formular. `path` (relativ zu `runtime.baseUrl`), `method` (Standard `POST`), `body` (`form` oder `json`, Standard `form`), `fields` (Name auf Wert, Werte nehmen `{connection.<Feld>}` und `{config.<Feld>}`), `cookies` (welche Cookies bleiben, Standard alle), `failIf` (Text, an dem ein abgelehnter Login im Weiterleitungsziel oder in der Antwort zu erkennen ist, etwa `authfail`), `ttlMinutes` (wie lange die Sitzung wiederverwendet wird, Standard 20). Nexxus meldet sich einmal an, schickt die Cookies bei jedem Aufruf mit und meldet sich neu an, wenn das System mit 401 antwortet. |

#### `runtime`

| `type` | Felder | Bedeutung |
|---|---|---|
| `rest` | `baseUrl` (`https://` oder `{config.x}`), `helper` (`graph`, `google`, `slack`, `none`), `pagination`, `errorEnvelope`, `headers` | Jede Aktion ist ein HTTP-Aufruf. Die Helfer stellen das Blättern für Microsoft Graph, Google und Slack ein. `pagination` nimmt `type: link`, `cursor` (mit `cursorParam`, `nextPath`), `page` (mit `pageParam`), `offset` (mit `offsetParam`, `totalPath`, `itemsPath`) oder `nextlink`. `errorEnvelope` (`okPath`, `messagePath`, `reconnectOn`) ist für Schnittstellen, die Fehler in einer erfolgreichen Antwort melden. `headers` sind feste Header, nie Geheimnisse. |
| `mcp` | `url` (`https://` oder `{config.x}`), `transport` (`streamable_http`, `sse`), `headers` | Die Werkzeuge kommen von einem entfernten MCP-Server, nexxus fragt sie dort ab. |
| `builtin` | `tools` (Muster über Werkzeugnamen), `remote` | Übernimmt Werkzeuge, die das nexxus-Backend schon hat. Jede Aktion nennt das Recht, für das sie steht. |
| `gateway` | `toolType`, `endpoint`, `tools` | Werkzeuge, die im KI-Gateway laufen. |

`builtin` und `gateway` verweisen auf Werkzeuge in nexxus selbst. Ein neuer Connector für ein fremdes System nimmt `rest` oder `mcp`.

#### `actions[]`

| Feld | Typ | Pflicht | Bedeutung |
|---|---|---|---|
| `key` | Text | ja | `[a-z0-9_]`, beginnt mit Buchstabe oder Ziffer. Der Werkzeugname `<key>__<Aktion>` darf höchstens 64 Zeichen haben. |
| `name` | Text | ja | Auf der Connector-Seite und auf der Bestätigungskarte |
| `description` | Text | ja | Was sie tut und wann man sie benutzt. Davon hängt ab, ob der KI-Assistent sie findet. |
| `kind` | `read`, `write` | nein | Standard `read` |
| `confirm` | `always`, `default`, `never` | nein | Standard: `always` bei `write`, `never` bei `read`. `default` fragt wie `always`. `never` ist bei einer schreibenden Aktion nicht erlaubt. |
| `method` | `GET`, `POST`, `PUT`, `PATCH`, `DELETE` | bei `rest` | |
| `path` | Text | bei `rest` | Beginnt mit `/`. Jedes `{name}` darin braucht eine Pfad-Eingabe dieses Namens. |
| `input` | Liste | nein | Die Parameter, siehe unten |
| `output` | Objekt | nein | `pick`: eine Liste von Pfaden wie `data[].id`, die die Antwort verkleinern. `maxChars`: eine Grenze für den Text, den der KI-Assistent liest, Standard 20.000 Zeichen. Siehe [Lange Antworten](#lange-antworten). |
| `pagination` | Objekt | nein | Blättern dieser Aktion, wenn es von `runtime.pagination` abweicht, mit denselben Feldern. `{type: none}` schaltet das Blättern für die Aktion ab. Für Schnittstellen, deren Endpunkte unterschiedlich geformt antworten. |

Felder in `input[]`: `name` (Pflicht), `type` (`string`, `integer`, `number`, `boolean`, `array`, `object`, Standard `string`), `required`, `location` (`path`, `query`, `body`, `header`; Standard `query` bei GET und DELETE, sonst `body`), `description`, `enum`, `default`, `min`, `max`, `items` (bei `array`), `properties` und `requiredProperties` (bei `object`), beide siehe unten.

Eine Liste (`type: array`) beschreibt mit `items` das JSON-Schema eines Eintrags. Fehlt `items`, erfährt der KI-Assistent nur, dass die Liste Text enthält, und schickt Text, auch wo die Schnittstelle Objekte erwartet. Die Tests des Builds verlangen deshalb `items` bei jeder Liste eines ausgelieferten Connectors. Für eine Liste von Texten reicht `items: { type: string }`. Die Empfänger von Outlook E-Mail sehen so aus:

```yaml
- name: toRecipients
  type: array
  required: true
  location: body
  items: &recipient
    type: object
    properties:
      emailAddress:
        type: object
        properties:
          address: { type: string }
          name: { type: string }
        required: [address]
    required: [emailAddress]
```

Ein Objekt (`type: object`) beschreibt mit `properties` seine Felder: je Feldname ein JSON-Schema wie bei `items`, auch verschachtelt. Eine Liste in einem Objekt braucht wieder `items`, auch das prüfen die Tests. `requiredProperties` nennt die Felder, die die Schnittstelle verlangt, etwa `requiredProperties: [id]` beim übergeordneten Ordner in Box; `required` sagt weiter nur, ob das Objekt selbst Pflicht ist. Felder, die `properties` nicht nennt, gehen trotzdem durch. Ein YAML-Anker (`&recipient` oben) erspart es, dasselbe Schema zweimal zu schreiben. Die Nachricht `message` von `send_mail` in Outlook E-Mail:

```yaml
- name: message
  type: object
  required: true
  location: body
  properties:
    subject: { type: string }
    body:
      type: object
      properties:
        contentType: { type: string }
        content: { type: string }
    toRecipients: { type: array, items: *recipient }
    ccRecipients: { type: array, items: *recipient }
    importance: { type: string, enum: [low, normal, high] }
```

Das KI-Gateway prüft jeden Aufruf gegen dieses Schema und gibt Abweichungen an den KI-Assistenten zurück. Setzen Sie `required`, `requiredProperties` und `enum` nur, wo die Schnittstelle sie wirklich verlangt, sonst scheitern auch gültige Aufrufe. Ein Feld, das die Schnittstelle mit `null` leert, bekommt keinen `type`, nur eine `description`: sonst lässt das Gateway das `null` weg, und das Feld bleibt, wie es war.

#### Lange Antworten

Der KI-Assistent liest die Antwort einer Aktion als Text, höchstens `output.maxChars` Zeichen. Vorher lässt `pick` nur die genannten Felder übrig, damit mehr Einträge hineinpassen.

Ist eine JSON-Antwort länger, kürzt nexxus an ganzen Einträgen ihrer längsten Liste auf oberster Ebene, etwa `value` bei Microsoft Graph oder einer Antwort, die selbst eine Liste ist. Die übrigen Felder bleiben, die Antwort bleibt gültiges JSON. Vor den Daten steht ein Hinweis mit der Zahl der gezeigten und aller Einträge, damit der KI-Assistent die Liste nicht für vollständig hält: `TEILERGEBNIS`, wenn die Aktion fortsetzen kann, sonst `UNVOLLSTÄNDIG`. Ist schon der erste Eintrag allein zu lang, zeigt nexxus ihn gekürzt. Alles andere kürzt nexxus nach Zeichen, mit `UNVOLLSTÄNDIG: gekürzt auf n von m Zeichen`: Text, JSON ohne Liste auf oberster Ebene und eine Liste, deren einziger Eintrag zu lang ist.

Eine gekürzte Liste liest der KI-Assistent weiter. Das Ergebnis endet dann mit „Weitere Ergebnisse“ und einem Wert für die Eingabe `nextPage`:

```text wrap
Termine im Zeitraum auflisten, HTTP 200:
TEILERGEBNIS: Die Liste „value“ zeigt hier Einträge 1 bis 40 von 118. Die übrigen 78 folgen mit „Weitere Ergebnisse“ am Ende. Nicht als vollständig behandeln: wo der Rest zählt, erst weiterlesen.
{"value":[...]}

Weitere Ergebnisse: dieselbe Aktion mit denselben Angaben und {"nextPage":"fortsetzung:40:118:3f2a9c1d:value"} aufrufen.
```

Mit diesem Wert und denselben Angaben ruft der KI-Assistent die Aktion noch einmal auf und bekommt die Einträge ab dem ersten fehlenden, mit `FORTSETZUNG` davor. nexxus speichert dafür nichts: Es fragt die Schnittstelle erneut und lehnt eine Fortsetzung mit anderen Angaben ab. Hat sich die Liste inzwischen geändert, steht das im Hinweis. Erst wenn die gekürzte Liste zu Ende gelesen ist, führt „Weitere Ergebnisse“ zur nächsten Seite der Schnittstelle.

Die Eingabe `nextPage` und damit die Fortsetzung bekommen nur lesende Aktionen, auf die eins davon zutrifft:

- Der Schlüssel beginnt mit `list_`, `search_`, `find_` oder `query_` oder enthält `search`.
- Ein Pfad in `output.pick` enthält `[]`.
- Die Aktion blättert mit ihrem eigenen `pagination`, `runtime.pagination` oder einem Helfer. Das gilt nur für GET.

Schreibende Aktionen und die übrigen lesenden kürzen mit `UNVOLLSTÄNDIG` und ohne Fortsetzung.

Bei Connectoren, die mit nexxus ausgeliefert werden, prüft der Test `PluginListPickSpec` im Build:

- Jede lesende Aktion eines REST-Connectors, deren Schlüssel nach Liste oder Suche aussieht (wie oben), hat ein `output.pick`. Sonst steht sie in `WITHOUT_PICK` in diesem Test, mit dem Grund, etwa weil die Anfrage ihre Felder schon selbst wählt (`$select`, `fields`, GraphQL).
- Zu einem Pick gehört eine Beispielantwort in der Form, die der Anbieter dokumentiert: `backend/src/test/resources/plugins/pick-samples/<connector>/<aktion>.json`. Jeder Pfad des Picks muss darin etwas finden, und das Ergebnis muss kleiner sein als die ganze Antwort. Ein Pfad, der nichts findet, ließe sein Feld sonst ohne Meldung weg.

Ein Pfad trennt an jedem Punkt. Felder wie `@odata.etag` lassen sich deshalb nicht auswählen. Die nächste Seite liest nexxus aus der ungekürzten Antwort, `@odata.nextLink` muss also nicht im Pick stehen.

#### `triggers[]`

| Feld | Bedeutung |
|---|---|
| `key`, `name`, `description` | Wie bei Aktionen |
| `mode` | `poll` (nexxus ruft in einem Abstand eine lesende Aktion auf) oder `webhook` (der Absender schickt an eine Adresse) |
| `action` | Bei `poll`: eine vorhandene **lesende** Aktion |
| `intervalMinutes` | Bei `poll`: der Standardabstand, mindestens 5 |
| `itemsPath` | Wo die Liste neuer Einträge in der Antwort steht, etwa `data.items[]` |
| `dedupeKey` | Bei `poll` Pflicht: der Pfad zur Kennung eines Eintrags, damit jeder Eintrag nur einmal auslöst |
| `promptTemplate` | Die deutsche Überschrift über den neuen Einträgen in der Nachricht an den Schedule |
| `pollArgs` | Feste Argumente für die abgefragte Aktion |
| `config` | Felder, die die Person beim Einrichten des Auslösers ausfüllt |

#### Felder in `config`, `connectionFields` und `config` eines Auslösers

| Feld | Bedeutung |
|---|---|
| `key` | `[A-Za-z][A-Za-z0-9_]`, eindeutig in der Liste |
| `label` | Pflicht. Erscheint so, wie es dasteht, auf Deutsch. |
| `type` | `string`, `text`, `url`, `password`, `number`, `integer`, `boolean`, `select` |
| `required`, `default`, `placeholder`, `description` | Wie die Namen sagen |
| `secret` | Verschlüsselt gespeichert und nie zurückgegeben. Bei `password` automatisch. |
| `options` | Bei `select`: einfache Werte oder `{value, label, en}` mit deutscher und optional englischer Beschriftung |

Ein Connector, der sich mit `oauth2` oder `client_credentials` anmeldet, bekommt die Felder `clientId` und `clientSecret` in seiner Konfiguration, auch wenn das Manifest sie nicht nennt.

#### `permissions[]`

Berechtigungsgruppen gibt es nur bei Connectoren mit `oauth2` und `oauth2_dcr`.

| Feld | Bedeutung |
|---|---|
| `key`, `name`, `description` | Die Gruppe, wie Personen sie sehen, etwa „Mails senden“ |
| `scopes` | Die Scopes, die diese Gruppe braucht, eine Teilmenge von `auth.scopes` |
| `actions` | Die Aktionen, die sie freischaltet. Jede Aktion gehört höchstens zu einer Gruppe. |
| `required` | Wird immer angefragt und lässt sich nicht abwählen |
| `default` | Beim ersten Verbinden angehakt. Standard `true`. |

Scopes ohne Gruppe werden immer angefragt. Aktionen ohne Gruppe sind immer verfügbar.

### Prüfmeldungen

Ein paar Meldungen, die Ihnen begegnen werden:

| Meldung | Lösung |
|---|---|
| `key '...' muss dem Ordnernamen '...' entsprechen.` | Ordner oder Schlüssel umbenennen, sodass sie gleich sind. |
| `icon.svg oder icon.png fehlt neben plugin.yml.` | Ein Symbol neben das Manifest legen. |
| `runtime.baseUrl '...' muss https sein (Platzhalter {config.x} erlaubt).` | `https://` oder einen Wert aus der Konfiguration verwenden. |
| `auth.type api_key braucht connectionFields oder ein geheimes config-Feld.` | Angeben, woher der Schlüssel kommt. |
| `actions....: confirm never ist nur für read erlaubt.` | Schreibende Aktionen müssen bestätigen. |
| `actions....: Werkzeugname ... ist länger als 64 Zeichen.` | Connector-Schlüssel oder Aktionsschlüssel kürzen. |
| `actions.....input....: path enthält {...} nicht.` | Eine Pfad-Eingabe braucht ihren Platzhalter in `path`. |
| `triggers....: poll nur über read-Aktionen.` | Ein Auslöser darf nur lesen. |
| `permissions gibt es nur für OAuth-Connectoren.` | Die Gruppen entfernen oder auf OAuth umstellen. |

## Was im Hintergrund passiert

<Flow
  steps={[
    { icon: 'save', title: 'Sie speichern', text: 'nexxus prüft den Connector nach denselben Regeln wie den Katalog.', tone: 'cyan' },
    { icon: 'activity', title: 'nexxus testet', text: 'Bei MCP-Connectoren vom Server aus, und speichert die Werkzeugliste.' },
    { icon: 'message-square-text', title: 'Ein Chat benutzt ihn', text: 'Die Werkzeuge kommen aus der gespeicherten Liste, ohne zusätzlichen Abruf.', tone: 'lavender' },
    { icon: 'shield-check', title: 'Jeder Aufruf wird geprüft', text: 'Freigabe, Rechte, Bestätigung und Netzregeln, dann wird die Antwort als fremder Inhalt markiert.' },
  ]}
/>

- **Werkzeugnamen.** Werkzeuge von MCP-Connectoren heißen nach dem Kürzel des Connectors und dem Werkzeugnamen des Servers. Werkzeuge Ihrer REST- und OpenAPI-Connectoren tragen die Vorsilbe des Connectors und den Aktionsschlüssel.
- **Schlüssel und Tokens bleiben auf dem Server.** Header-Werte, API-Schlüssel und Tokens liegen verschlüsselt und erreichen nie das Modell, das Gateway oder den Browser.
- **Ergebnisse von außen werden markiert.** Der KI-Assistent bekommt gesagt, dass das, was ein Server zurückgibt, Information ist und keine Anweisung.
- **Jede Anfrage läuft durch die Netzregeln,** auch Tests, OpenAPI-Downloads und Weiterleitungen.

## Wenn etwas nicht klappt

### Der Verbindungstest scheitert

Der Test nennt die gescheiterte Stufe und eine Erklärung:

| Meldung | Bedeutung und Lösung |
|---|---|
| `Der Servername lässt sich vom Server aus nicht auflösen.` | Der Hostname lässt sich vom nexxus-Server aus nicht auflösen. Adresse prüfen, oder ob der Server in einem Netz steht, das nexxus sieht. |
| `Adresse vom Server aus nicht erreichbar (...)` | Vom nexxus-Server aus antwortet unter dieser Adresse nichts: Firewall, geschlossener Port oder keine Route. |
| `Die verschlüsselte Verbindung (TLS) kommt nicht zustande: ...` | Das Zertifikat wird nicht anerkannt. Bei einer firmeneigenen Zertifizierungsstelle die CA unter <Ui>Eigenes CA-Zertifikat (PEM)</Ui> hinterlegen. |
| `Anmeldung abgelehnt (401): Header prüfen, ...` | Der Schlüssel fehlt oder ist falsch. Header oder <Ui>Meine Zugangsdaten</Ui> prüfen. |
| `Zugriff verweigert (403): ...` | Der Server kennt den Schlüssel, lässt ihn aber nicht zu. |
| `Unter dieser Adresse gibt es keinen MCP-Server (404). ...` | Den Pfad prüfen, oft endet er auf `/mcp` oder `/sse`. |
| `Antwortet, spricht aber kein MCP (...)` | Den anderen <Ui>Transport</Ui> versuchen. |
| `Private Adresse (...), für diesen Mandanten nicht freigegeben.` | Die Adresse liegt in einem privaten Netz, das nicht freigegeben ist. Einen Administrator bitten, sie in die Netz-Freigabe aufzunehmen. |
| `Unverschlüsseltes http:// ist nur für freigegebene interne Adressen erlaubt; bitte https:// verwenden.` | `https://` verwenden oder die interne Adresse mit erlaubtem http freigeben lassen. |
| `Metadaten-Dienste der Cloud sind nie erreichbar.` | Metadaten-Adressen von Cloud-Anbietern sind immer gesperrt. |

### Das Speichern scheitert

| Meldung | Lösung |
|---|---|
| `Die Adresse enthält noch einen Platzhalter (z. B. IP:PORT). Bitte die echte Adresse eintragen.` | Die echte Adresse eintragen. |
| `Die Adresse muss mit http:// oder https:// beginnen und einen Server nennen.` | Die Adresse korrigieren. |
| `Höchstens 50 eigene Connectoren je Person.` | Einen Connector löschen oder übertragen, den Sie nicht mehr brauchen. |
| `Die Bestätigung von Schreibwerkzeugen lässt sich nur bei „Nur ich“ abschalten.` | Vor dem Teilen die Bestätigung wieder einschalten. |
| `Keine Berechtigung, über „Nur ich" hinaus zu teilen.` | Zum Teilen brauchen Sie `ai.plugin.share`. |
| `Die Spezifikation ist größer als 5 MB.` | Die Beschreibung aufteilen oder nur den nötigen Teil einfügen. |
| `Das ist keine OpenAPI- oder Swagger-Beschreibung (Feld openapi bzw. swagger fehlt).` | Die Datei ist keine OpenAPI-Beschreibung. |
| `Die Spezifikation nennt keinen Server; bitte die Basis-URL angeben.` | Die Basis-URL selbst eintragen. |
| `Keine SKILL.md im ZIP gefunden` | Die `SKILL.md` an die Wurzel des ZIP oder in seinen einen Ordner legen. |
| `SKILL.md enthält keine Anweisungen` | Unter dem Frontmatter die Anweisungen ergänzen. |

## Nächste Schritte

<CardGrid>
  <LinkCard title="Connector einrichten" description="Katalog-Connectoren installieren und verbinden." href="/de/plugins/set-up/" />
  <LinkCard title="Was Connectoren sind" description="Arten, Anmeldung, Berechtigungsgruppen und der Weg eines Werkzeugaufrufs." href="/de/plugins/overview/" />
</CardGrid>