# Agent-Zugang (KI-Support & Automatisierung)

## Was ist das?

Programme (der KI-Support-Assistent, eigene Automatisierungen, Fremdsysteme)
können auf einen begrenzten, klar definierten Satz von Funktionen Ihrer
Organisation zugreifen — den „Tool-Layer" — ohne sich als Mensch anzumelden.
Derselbe Zugang authentifiziert auch die [REST-API](https://www.testlabiq.com/hilfe/rest-api)
(`/api/v1/projects`, `/api/v1/test-cases`, …).

Es gibt zwei Wege:

- **Anmeldung per OAuth** (für KI-Assistenten wie Claude, ChatGPT, Cursor
  oder VS Code): Sie tragen nur die Adresse ein, melden sich im Browser an und
  stimmen zu. Das richten Sie selbst ein, ohne Token — siehe Abschnitt
  „Anbindung über MCP" unten.
- **Agent-Token** (für Automatisierungen ohne Menschen davor, z. B. Skripte
  oder Server): ein festes Token im Header. Diese Tokens richten wir für Sie
  ein — eine eigene Oberfläche zum Ausstellen gibt es dafür noch nicht;
  wenden Sie sich an unser Team.

## So funktioniert es

- **Rechte:** Jeder programmatische Zugriff läuft über dasselbe Rechtemodell
  wie ein menschliches Mitglied und sieht ausschliesslich Ihre eigene
  Organisation. Ein Token bekommt beim Anlegen eine Rolle
  (`VIEWER`/`MEMBER`/`ADMIN`, Default `VIEWER`) — sie bestimmt, welche der
  unten genannten Tools es nutzen darf, genau wie bei einem menschlichen
  Mitglied dieser Rolle. `OWNER` ist für Tokens ausgeschlossen: Mitgliederrechte
  ändern bleibt ausschliesslich menschlichen Personen vorbehalten.
- **Nachvollziehbar:** Jede Aktion steht im Audit-Log mit Akteurstyp *Agent*,
  bei OAuth zusätzlich mit der Person, in deren Auftrag die App handelt.

### Verfügbare Tools

- `search_docs` — durchsucht diese Hilfe-Dokumentation.
- `get_org_overview` — Kennzahlen (Projekte, Prüfstände, Prüflinge, …).
- `get_calibration_status` — fällige/überfällige Gerätekalibrierungen.
- `list_recent_audit_events` — jüngste Änderungen (nur mit Admin-Rolle).
- `get_webhook_deliveries` — Webhook-Zustellversuche (nur mit Admin-Rolle).
- `get_ingestion_deliveries` — Messdaten-Zustellungen (REST/MQTT) mit
  Erfolg/Fehler je Prüfstand.
- `get_report_status` — aktueller Berichtsstatus und gespeicherte Fehlerursache,
  optional gefiltert nach Bericht oder Projekt.
- `get_capacity_forecast` — Kapazitätsprognose je Prüfstandstyp (Auslastung,
  Spitzenlast, Rückstand, fehlende Prüfstände), optional als Was-wäre-wenn;
  speichert nichts (siehe [Kapazitätsprognose](https://www.testlabiq.com/hilfe/kapazitaetsprognose)).
- `list_projects`, `list_test_runs`, `list_stations`, `find_test_objects`,
  `list_nonconformances`, `list_equipment`, `list_customers`, `list_test_cases`,
  `list_station_types`, `list_test_object_types`, `list_equipment_types`,
  `list_test_run_items`, `get_custody_trail` — lesender Zugriff auf die
  jeweiligen Fachdaten.

### Schreibende Tools (ab Rolle `MEMBER`)

- `create_station`/`create_station_type`, `create_test_object`/
  `create_test_object_type`, `create_equipment`/`create_equipment_type`,
  `create_customer`, `create_project`, `update_project`, `update_customer`,
  `create_test_case`, `update_test_case`, `record_custody_event`,
  `create_nonconformance`, `create_test_run`, `create_test_run_item` — legen
  direkt Daten an bzw. ändern sie. `create_test_run` legt eine neue
  Testsequenz in einem Projekt an (braucht einen festen Startzeitpunkt oder
  mindestens eine Abhängigkeit zu einer anderen Sequenz); `create_test_run_item`
  fügt ihr einen Prüfschritt hinzu, wahlweise mit einem Testfall aus der
  Bibliothek oder einem neu angelegten. Anders als
  im Chat des KI-Support-Assistenten (dort erst nach Bestätigung durch die
  Kundschaft) führt ein Programm mit einem eigenen Token diese Aktionen
  **sofort** aus, sobald es das Tool aufruft — es gibt hier keine
  Bestätigungs-Zwischenstufe. Ein solches Token gehört deshalb nur in
  vertrauenswürdige eigene Automatisierungen, nicht in die Hände Dritter.
  `update_project`/`update_customer`/`update_test_case` ersetzen bei jedem
  Aufruf den vollständigen Datensatz — ein weggelassenes optionales Feld wird
  geleert, nicht unverändert gelassen. Ebenso `update_station`,
  `update_test_object`, `update_equipment` (das Foto lässt sich darüber
  nicht ändern).
- Dazu: `update_station_status`, `set_station_maintenance_window`,
  `update_equipment_status` (Status/Wartungstermin setzen),
  `update_project_status_mode`, `create_project_baseline`,
  `activate_project_baseline`, `restore_project_revision`,
  `restore_test_run_revision` (Terminplanung/Revisionen eines Projekts bzw.
  einer Testsequenz), `create_qualification`, `grant_qualification`,
  `create_absence_for_member`, `set_station_operators` (Personalverwaltung),
  `assign_custody_code` (scannbaren Code vergeben) und
  `create_document_folder`.
- Prüfschritte pflegen: `set_test_run_item_station`,
  `reassign_test_run_items_station`, `set_test_run_item_dependencies`,
  `set_test_run_dependencies`, `set_test_run_item_start`,
  `set_test_run_start`, `set_test_run_item_progress`,
  `add_test_run_item_note`, `set_test_run_item_assignee`,
  `set_test_run_item_equipment`, `update_test_run_item_due_date`,
  `update_test_run_status_mode` — Prüfstand-Zuordnung, Terminierung,
  Abhängigkeiten, Fortschritt, Notizen, Zuständigkeit, Rückverfolgbarkeits-
  Equipment und Fälligkeit einzelner Prüfschritte bzw. einer ganzen
  Testsequenz.
- Meilensteine: `create_milestone`, `update_milestone`,
  `set_milestone_reached`, `set_milestone_date` — optional automatisch
  erreicht, sobald eine bestimmte Testsequenz oder ein bestimmter
  Prüfschritt besteht.
- **Bewusst nicht dabei:** Löschen, Mitgliederrechte ändern, Einstellungen
  (Webhooks, API-Keys) sowie die eigentliche Testlauf-**Ausführung**
  (Prüfergebnis erfassen, Prüfschritt-Status auf bestanden/fehlgeschlagen
  setzen, strukturierte Messergebnisse bearbeiten, Massenänderungen) —
  diese Logik hat Webhook-, Benachrichtigungs- und
  Meilenstein-Seiteneffekte und noch keine automatisierte Testabdeckung;
  sie wird erst mit eigenen Tests headless gemacht, nicht mechanisch
  verschoben. Ebenfalls noch nicht angebunden: Dateien/Fotos hochladen.

## Anbindung über MCP (Model Context Protocol)

TestLabIQ hat einen eingebauten MCP-Server. MCP ist ein offener Standard —
der Server ist an keinen bestimmten KI-Anbieter gebunden. Jeder Client, der
den MCP-Transport **Streamable HTTP** spricht, funktioniert.

Adresse: `https://app.testlabiq.com/api/v1/agent/mcp`

### Empfohlen: Anmeldung per OAuth

Tragen Sie in Ihrem KI-Client nur die Adresse ein. Beim ersten Verbinden
öffnet der Client ein Browserfenster:

1. Sie melden sich wie gewohnt bei TestLabIQ an.
2. Sie sehen, welche App Zugriff möchte und wohin es danach weitergeht.
3. Sie wählen die **Organisation** und **was die App darf**: *Nur lesen*,
   *Lesen und bearbeiten* oder *Verwalten* — höchstens Ihre eigene Rolle.
4. Mit **Zulassen** ist die App verbunden.

Die App handelt danach **in Ihrem Auftrag**: im Audit-Log steht jede Aktion
als *Agent — im Auftrag von* Ihnen. Sie kann nie mehr als Sie selbst: wird
Ihre Rolle herabgestuft oder verlassen Sie die Organisation, gilt das sofort
auch für die App. Unter **Einstellungen → Meine Einstellungen → Verbundene
Apps** sehen Sie alle Verbindungen mit letzter Nutzung und können jede
sofort trennen.

So geht es in gängigen Clients:

- **Claude (Web, Desktop, Mobil)** und **ChatGPT**: einen eigenen
  Konnektor hinzufügen (bei ChatGPT im Entwicklermodus) und als URL die
  Adresse oben eintragen. Anmeldung: OAuth.
- **Claude Code**:

  ```
  claude mcp add -s user --transport http testlabiq https://app.testlabiq.com/api/v1/agent/mcp
  ```

  danach in einer Sitzung `/mcp` aufrufen und „Authenticate" wählen.
- **Cursor** (`~/.cursor/mcp.json`):

  ```json
  { "mcpServers": { "testlabiq": { "url": "https://app.testlabiq.com/api/v1/agent/mcp" } } }
  ```

- **VS Code / GitHub Copilot** (`.vscode/mcp.json` oder „MCP: Open User
  Configuration"):

  ```json
  { "servers": { "testlabiq": { "type": "http", "url": "https://app.testlabiq.com/api/v1/agent/mcp" } } }
  ```

- **Andere Clients**: Adresse eintragen; unterstützt der Client OAuth für
  MCP-Server, startet die Anmeldung von selbst. Er findet unseren
  Anmeldeserver automatisch (Metadaten nach RFC 9728/8414) und registriert
  sich selbst (Dynamic Client Registration) — Sie müssen nichts weiter
  konfigurieren.

Der Name, unter dem Sie den Server im Client eintragen (oben `testlabiq`),
ist frei wählbar. Für mehrere Organisationen verbinden Sie die App einfach
mehrfach — je Verbindung wählen Sie eine Organisation.

### Alternativ: Agent-Token im Header

Für Automatisierungen ohne Menschen davor (Skripte, Server, CI) gibt es das
feste Agent-Token. Es geht im Header `x-agent-token` mit (alternativ
`Authorization: Bearer <token>`); eine Anmeldung im Browser entfällt.

**Claude Code:**

```
claude mcp add -s user --transport http testlabiq \
  https://app.testlabiq.com/api/v1/agent/mcp \
  -H 'x-agent-token: ${TESTLABIQ_TOKEN}'
```

Die einfachen Anführungszeichen sind wichtig: so landet der Platzhalter in
der Konfiguration und wird bei jedem Verbindungsaufbau frisch aus der
Umgebung aufgelöst — mit doppelten Anführungszeichen expandiert die eigene
Shell sofort und der Klartext steht doch in der Datei.

**Cursor:** wie oben, zusätzlich
`"headers": { "x-agent-token": "${env:TESTLABIQ_TOKEN}" }`.

**VS Code:** wie oben, zusätzlich
`"headers": { "x-agent-token": "${input:testlabiq-token}" }` und ein
passender Eintrag unter `"inputs"` (`"type": "promptString"`,
`"password": true`) — VS Code fragt das Token dann einmal ab und speichert es
verschlüsselt.

**Codex CLI** (`~/.codex/config.toml`):

```toml
[mcp_servers.testlabiq]
url = "https://app.testlabiq.com/api/v1/agent/mcp"
bearer_token_env_var = "TESTLABIQ_TOKEN"
```

**Eigene Agenten** mit dem offiziellen MCP-SDK (TypeScript):

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const client = new Client({ name: "mein-agent", version: "1.0.0" });
await client.connect(
  new StreamableHTTPClientTransport(new URL("https://app.testlabiq.com/api/v1/agent/mcp"), {
    requestInit: { headers: { "x-agent-token": process.env.TESTLABIQ_TOKEN! } },
  }),
);
const { tools } = await client.listTools();
```

In Python entsprechend `streamablehttp_client(url, headers={"x-agent-token": token})`.

### Verbindung ohne Client testen (Agent-Token)

```
curl -s https://app.testlabiq.com/api/v1/agent/mcp \
  -H "x-agent-token: $TESTLABIQ_TOKEN" \
  -H "content-type: application/json" \
  -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Kommt eine Liste von Tools zurück, ist der Zugang in Ordnung und ein
verbleibendes Problem liegt in der Client-Konfiguration. Ein `401` heisst:
Token fehlt, ist falsch oder gesperrt.

### Welche Organisation gilt?

Das ist **nicht** pro Aufruf wählbar, und zwar mit Absicht: kein einziges Tool
nimmt eine Organisation als Parameter entgegen. Die Organisation kommt
ausschliesslich aus dem Zugang selbst — so kann auch eine manipulierte
Anweisung an die KI sie nicht umbiegen.

- **Bei OAuth** wählen Sie die Organisation beim Zustimmen; sie gilt für
  genau diese Verbindung.
- **Ihr eigenes Agent-Token** ist beim Ausstellen fest an genau eine
  Organisation gebunden. Wer mehrere Organisationen bedienen möchte, lässt
  sich je Organisation ein Token ausstellen und richtet je Token einen
  eigenen MCP-Zugang ein (z. B. `testlabiq-labor-nord`,
  `testlabiq-labor-sued`).
- **Beim Betreiber-Zugang** (ein einziges Token über alle Organisationen
  hinweg) gehört die Ziel-Organisation in den zusätzlichen Header
  `x-agent-org` — als Organisations-Slug oder -ID. Fehlt der Header, wird
  bewusst gar nichts aufgelöst, damit ein vergessener Header nicht in einer
  zufälligen Organisation landet.

## Typische Probleme

- **„Ich finde keine Seite, um ein Token anzulegen oder zu sperren."** Für
  KI-Assistenten brauchen Sie keins — verbinden Sie per OAuth (siehe oben),
  getrennt wird unter *Verbundene Apps*. Feste Agent-Tokens für
  Automatisierungen richten wir ein; wenden Sie sich dafür oder bei
  Auffälligkeiten an unser Team.
- **„Der Client meldet ‚needs authentication' / bietet eine Anmeldung an."**
  Das ist bei OAuth der normale erste Schritt — Anmeldung starten. Haben Sie
  ein Agent-Token eingetragen, ist es fehlend oder ungültig (oft: die
  Umgebungsvariable ist in der Umgebung, aus der der Client startet, nicht
  gesetzt; viele Clients lesen keine `.env`-Datei).
- **„Auf der Zustimmungsseite ist meine Organisation ausgegraut."** Der
  Agent-Zugang ist für diese Organisation abgeschaltet (Not-Aus). Wenden Sie
  sich an eine Administratorin bzw. einen Administrator.
- **„Ich kann nur ‚Nur lesen' wählen."** Eine App bekommt höchstens Ihre
  eigene Rolle.
- **„Die App war verbunden und ist plötzlich wieder abgemeldet."** Mögliche
  Gründe: Sie (oder die App selbst) haben die Verbindung getrennt; Sie sind
  nicht mehr Mitglied der Organisation; oder die App hat ein bereits
  verbrauchtes Erneuerungs-Token ein zweites Mal geschickt — das werten wir
  als möglichen Diebstahl und trennen die Verbindung vorsorglich. Der Grund
  steht im Audit-Log („KI-App getrennt"). Einfach erneut verbinden.
- **„Die App darf etwas nicht, das ich selbst darf."** Prüfen Sie unter
  *Verbundene Apps*, welche Rolle Sie beim Zustimmen gewählt haben; für mehr
  Rechte trennen und mit höherer Rolle neu verbinden.
- **„401 / Ungültiges Token."** Das eingerichtete Token ist falsch oder
  gesperrt — bzw. bei OAuth: die Verbindung wurde getrennt oder der
  Agent-Zugang der Organisation abgeschaltet.
- **„403 / Keine Berechtigung."** Der eingerichtete Zugang darf dieses Tool
  nicht nutzen. Die Diagnose-Tools zu Audit und Webhooks setzen Admin-Rechte
  voraus.
- **„Der Agent sieht Daten einer anderen Organisation."** Kann nicht
  passieren: jeder Zugriff ist an genau eine Organisation gebunden, die
  Mandantentrennung gilt auch hier auf Datenbankebene.

---

Quelle: https://www.testlabiq.com/hilfe/agent-tokens
