Comet Opik

offiziell

Fragen Sie Ihre Opik-Logs, Traces, Prompts und alle anderen Telemetriedaten Ihrer LLMs in natürlicher Sprache ab und analysieren Sie diese.

Was kann man mit Comet Opik MCP machen?

  • Abfragen von Traces nach Projekt — Frage, welche Traces in einem Projekt heute fehlgeschlagen sind, mit Filtern für Fehlerinformationen, Dauer oder Tokenverbrauch.
  • Beliebige Opik-Entität lesen — Rufe ein Projekt, einen Trace, einen Span, ein Dataset, ein Experiment, einen Prompt, einen Thread oder ein Diagnostics-Problem anhand der ID, des Namens oder der opik://-URI ab.
  • Scores und Kommentare protokollieren — Bewerte einen Trace anhand einer Feedback-Metrik mit einer Begründung oder füge über das Schreibtool Kommentare hinzu.
  • Prompt-Versionen speichern — Erstelle und speichere neue Prompt-Versionen zusammen mit Datasets und Experimenten.
  • Schreibschemas prüfen — Frage nach dem Schema eines Schreibvorgangs, um vor dem Senden eine gültige Payload zu erstellen.
  • Projektstatus prüfen — Lies ein Projekt aus, um Trace-Anzahl, Fehlerrate, durchschnittliche Dauer und Gesamtkosten der letzten 7 Tage abzurufen.

Dokumentation

Opik MCP Server

Der offizielle Model Context Protocol (MCP)-Server für Opik, die Open-Source-Plattform für LLM-Beobachtbarkeit und -Evaluierung, entwickelt von Comet. Verbinde deinen KI-Host (Claude Code, Cursor, VS Code Copilot, Codex, opencode oder einen beliebigen MCP-Client) direkt mit deinem Opik-Arbeitsbereich: Lies Traces, protokolliere Scores und speichere Prompt-Versionen – alles direkt im Chat.

Entwickelt für LLM-Entwickler, die Opik bereits nutzen und es über denselben KI-Assistenten steuern möchten, mit dem sie programmieren.

You:    "Which traces in project 'demo' failed today?"
Claude: → list(entity_type="trace", project_name="demo") → "Three traces failed…"

You:    "Score trace 7f2e… 0.9 on helpfulness with reason 'great recovery'."
Claude: → write(score.create) → done

Schnellstart

Mit einem Befehl richtest du Opik in den KI-Clients auf deinem Rechner ein, einschließlich Claude Code. Der Befehl findet deine Opik-Instanz (die in ~/.opik.config gespeicherte, eine auf localhost laufende oder fragt dich, welche du verwenden möchtest), registriert den MCP-Server, installiert das Opik-Skill-Paket und überprüft die Verbindung. Bei Opik Cloud musst du keinen API-Schlüssel verwalten: Dein Client meldet dich im Browser an. Benötigt werden uv und kein Opik SDK:

uvx opik@latest mcp configure

Ohne Terminal, etwa über einen Coding-Agenten oder ein Skript, gib den Client an:

uvx opik@latest mcp configure --ai-client claude-code --skills

--ai-client akzeptiert außerdem codex, cursor, vscode und opencode. Bei dieser Ausführung wird die in ~/.opik.config gespeicherte Opik-Instanz samt API-Schlüssel verwendet oder eine auf localhost erreichbare. Andernfalls wird abgebrochen und nach --deployment gefragt.

Ein Coding-Agent, der mit „install opik mcp“ beauftragt wird, erhält unter uvx opik-mcp@latest --help die vollständigen Schritte, einschließlich der Fragen an den Benutzer. Sie entsprechen den Anweisungen unter Installation mit einem Coding-Agenten.

Wenn du den Server manuell mit den Client-Befehlen unter Manuelle Einrichtung registrierst, werden die verwendete Opik-Instanz nicht überprüft und das Skill-Paket nicht installiert. Das ist daher für Clients gedacht, die vom Installer nicht unterstützt werden.

Deine Opik-InstanzServerTransportAnmeldung
Opik Cloud (www.comet.com)der gehostete Server, betrieben von CometStreamable HTTPim Browser (OAuth); kein API-Schlüssel
Selbst gehostete Comet-Plattform, Open-Source-Opikder lokale Server, dieses PaketstdioUmgebungsvariablen; ein API-Schlüssel nur, wenn die Bereitstellung ihn benötigt

Clients laden MCP-Server beim Start einer Sitzung. Starte daher anschließend eine neue Sitzung.

Einrichtungsanleitung, Fehlerbehebung und FAQ: comet.com/docs/opik/mcp-server.


Opik Cloud: der gehostete Server

Comet betreibt den Server unter https://www.comet.com/opik/api/v1/mcp. Dein Client verbindet sich über HTTP und öffnet bei der ersten Verwendung ein Browserfenster zur Anmeldung. Es muss nichts installiert und kein API-Schlüssel oder Arbeitsbereich eingerichtet werden: Der Server verwendet den Arbeitsbereich, den du bei der Anmeldung auswählst. Füge ihn hinzu, starte eine neue Sitzung und frage: „list my Opik projects“.

Mit dem Befehl unter Schnellstart richtest du den Server für Claude Code, Codex, Cursor, VS Code Copilot und opencode samt Skill-Paket ein. In Claude Code erledigt das Plugin dasselbe mit einem Befehl. Über die Schaltflächen unten kannst du ihn mit einem Klick zu Cursor oder VS Code hinzufügen. Weitere Möglichkeiten zur manuellen Registrierung findest du unter Manuelle Einrichtung.

Add to Cursor Install in VS Code

Claude Code-Plugin

Das Plugin opik installiert die Opik-Skills und registriert den gehosteten MCP-Server für Opik Cloud:

/plugin install opik --marketplace comet-ml/opik-mcp

Bei Claude Code vor Version 2.1.275 führe /plugin marketplace add comet-ml/opik-mcp und anschließend /plugin install opik@opik aus. Die Skills werden als opik:<skill> geladen, zum Beispiel opik:opik-instrument, und /mcp zeigt den Server als plugin:opik:opik-cloud an. Der Server gehört zu Opik Cloud. Starte eine neue Sitzung und melde dich dann über /mcp → Authenticate an. Für eine selbst gehostete Comet-Plattform, auf der der MCP-OAuth-Server läuft, füge ihn mit claude mcp add --transport http opik-mcp https://<host>/opik/api/v1/mcp hinzu. Für alle anderen selbst gehosteten oder Open-Source-Opik-Instanzen verwende den Befehl unter Schnellstart. Deaktiviere anschließend plugin:opik:opik-cloud in /mcp. Claude Code aktualisiert ein Plugin aus diesem Marketplace nicht automatisch: Führe /plugin marketplace update opik und anschließend /plugin update opik@opik aus oder aktiviere die automatische Aktualisierung des Marketplaces unter /plugin. Dieser Marketplace stellt main bereit, das der letzten Veröffentlichung voraus sein kann. Ein Update wird erst bei einer Versionsänderung des Plugins bereitgestellt, also mit jeder Veröffentlichung.

Wenn du zuvor opik-mcp unter derselben URL hinzugefügt hast, behält Claude Code deinen Eintrag und überspringt den des Plugins. Wenn dein Eintrag ein anderer Server ist, etwa der lokale uvx opik-mcp, werden beide geladen. Führe claude mcp remove opik-mcp aus, um nur den des Plugins zu behalten. Die Skills aus dem Skill-Paket werden zusätzlich zu den Kopien des Plugins geladen. Entferne sie mit npx skills remove --global --agent claude-code; dabei wirst du gefragt, welche Skills entfernt werden sollen.


Selbst gehostetes und Open-Source-Opik: der lokale Server

opik-mcp läuft auf deinem Rechner: Der Client startet ihn mit uvx opik-mcp und kommuniziert über stdio mit ihm. Mit dem Befehl unter Schnellstart richtest du ihn über dein ~/.opik.config oder eine lokale Opik-Instanz ein. Informationen zur manuellen Registrierung findest du unter Manuelle Einrichtung. Installiere uv einmalig. Beim ersten Start lädt es das Paket und bei Bedarf Python 3.13 herunter:

curl -LsSf https://astral.sh/uv/install.sh | sh   # macOS / Linux
# or: brew install uv

uvx opik-mcp verwendet die von uv zwischengespeicherte Kopie erneut und startet daher schnell. uv cache clean opik-mcp sorgt dafür, dass beim nächsten Start die neueste Version heruntergeladen wird. uvx opik-mcp@latest fragt bei jedem Start PyPI ab, was etwa anderthalb Sekunden zusätzlich dauert. Codex wartet mcp_optional_startup_grace_ms (standardmäßig 1 s) auf Server, bevor es die erste Tool-Liste erstellt. Ein langsamerer Start kann dazu führen, dass die Tools im ersten Durchlauf fehlen. Die einmaligen Befehle in dieser README (opik mcp configure, opik mcp status, --help, --check) enthalten @latest. Dadurch wird nie eine Kopie verwendet, die uv vor Monaten zwischengespeichert hat.

Umgebungsvariablen verweisen den Server auf deine Opik-Instanz:

Deine Opik-InstanzUmgebungsvariablen
Open-Source-Opik auf diesem RechnerOPIK_URL=http://localhost:5173/api
Open-Source-Opik auf einem ServerOPIK_URL=https://<host>/api, außerdem OPIK_API_KEY nur, wenn die Bereitstellung eine Authentifizierung hinzufügt
Selbst gehostete Comet-Plattform (die Opik-Benutzeroberfläche befindet sich unter https://<host>/opik)COMET_URL_OVERRIDE=https://<host>, OPIK_WORKSPACE, OPIK_API_KEY
  • Open Source stellt seine API unter /api bereit und hat einen Arbeitsbereich, default. Daher ist kein OPIK_WORKSPACE erforderlich. COMET_URL_OVERRIDE würde den Server auf /opik/api verweisen, das Open Source nicht bereitstellt.
  • Eine selbst gehostete Comet-Plattform hat benannte Arbeitsbereiche. Setze OPIK_WORKSPACE auf das Segment nach /opik/ in deiner Opik-URL. Wenn du es weglässt, werden Lesezugriffe aus dem Standardarbeitsbereich deines Kontos ausgeführt, ohne dass ein Fehler darauf hinweist.
  • Eine selbst gehostete Comet-Plattform, auf der der MCP-OAuth-Server läuft (standardmäßig deaktiviert), kann stattdessen den gehosteten Ablauf unter https://<host>/opik/api/v1/mcp verwenden.
  • Ersetze alle Werte. Der Server lehnt Platzhalter für Arbeitsbereiche wie <your-workspace> oder ${input:OPIK_WORKSPACE} ab. Eine Platzhalter-URL wird unverändert gesendet und die Verbindung schlägt fehl.
  • OPIK_MCP_ANALYTICS_SOURCE="" im Block env verhindert, dass eine selbst gehostete Installation bei Telemetrieereignissen als Cloud-Comet gekennzeichnet wird.

Prüfe die Einstellungen, bevor du den Server zu einem Client hinzufügst: Starte ihn mit denselben Umgebungsvariablen und --check. Dabei wird Opik einmal aufgerufen und der Arbeitsbereich sowie die Anzahl der gefundenen Projekte ausgegeben. Bei Problemen wird angezeigt, was zu korrigieren ist, samt Link zur Dokumentation. Der Befehl wird mit Exit-Code 0 oder 1 beendet. Ein Client kann das nicht vor einer neuen Sitzung überprüfen: Claude Code zeigt auch bei einem falschen Schlüssel „Connected“ an, und Codex startet bis dahin nichts.

OPIK_URL=http://localhost:5173/api uvx opik-mcp@latest --check

Registriere ihn anschließend bei deinem Client: der lokale Server, manuell.


Installation mit einem Coding-Agenten

Für einen KI-Agenten, der mit der Installation des Servers beauftragt wird, etwa mit „install opik mcp“. Ziel ist es, den Server für die Opik-Instanz des Benutzers zu registrieren, das Opik-Skill-Paket zu installieren und den Benutzer anzumelden. Ermittle, welche Opik-Instanz auf diesem Rechner verwendet wird, und frage den Benutzer nur nach Informationen, die du nicht selbst herausfinden kannst: eine Frage pro Nachricht und jede Antwort abwarten, bevor du die nächste Frage stellst. Der Installer in Schritt 3 erledigt die gesamte Einrichtung in einem Durchlauf. Kläre daher die Schritte 1 und 2, bevor du ihn ausführst. uvx opik-mcp@latest --help gibt diese Schritte aus.

  1. Prüfe, was bereits vorhanden ist.

    uvx opik@latest mcp status
    

    Der Befehl zeigt die in ~/.opik.config gespeicherte Opik-Instanz (URL und Arbeitsbereich, niemals den Schlüssel) sowie die Clients, bei denen der Server bereits eingerichtet ist. Führe in Claude Code außerdem claude mcp list aus: Der Befehl zeigt claude.ai-Connectoren und Einträge unter anderen Namen an. Er gibt auch den Befehl jedes Eintrags aus. Bei einem alten npx-Eintrag kann dieser einen API-Schlüssel enthalten: Gib ihn nicht weiter.

    • Ein Server für https://www.comet.com/opik/api/v1/mcp unter einem beliebigen Namen, etwa als claude.ai-Connector, bedeutet, dass er bereits registriert ist. Füge keinen zweiten hinzu. Installiere nur das Skill-Paket mit npx skills add comet-ml/opik-skills -g --all. Fahre mit Schritt 4 fort, wenn der Server als ! Needs authentication angezeigt wird.
    • Der Installer ersetzt einen vorhandenen Eintrag für opik-mcp ohne Rückfrage, etwa einen für den alten npx-Server. Frage den Benutzer, bevor du ihn ausführst.
  2. Ermittle die Opik-Instanz des Benutzers.

    • In ~/.opik.config gespeichert: Verwende sie und teile dem Benutzer mit, welche Instanz du einrichtest. Der Installer liest sie einschließlich des API-Schlüssels aus. Frage also nicht nach einem Schlüssel.
    • Kein ~/.opik.config: curl -s http://localhost:5173/api/is-alive/ping. Eine Antwort bedeutet, dass auf diesem Rechner eine Open-Source-Opik-Instanz läuft. In einer abgeschotteten Shell, etwa der von Codex, kann eine ausbleibende Antwort bedeuten, dass die Shell keinen Netzwerkzugriff hat und nicht, dass keine Opik-Instanz vorhanden ist.
    • Beides trifft nicht zu: Frage nach und wähle nicht selbst eine Instanz aus. Eine Opik-URL im Projekt, etwa OPIK_URL_OVERRIDE in .env, macht daraus eine Ja-Nein-Frage. Andernfalls frage: „Welche Opik-Instanz verwendest du: Opik Cloud (www.comet.com), eine Open-Source-Opik-Instanz (ihre URL) oder eine selbst gehostete Comet-Plattform (ihre URL und ihr Arbeitsbereich)?“
  3. Führe den Installer für den Client aus, in dem du arbeitest. Er installiert das Opik-Skill-Paket zusammen mit dem Server, mit oder ohne --skills. Lass das Flag in einem Befehl stehen, den du dem Benutzer zur späteren Ausführung gibst. Bei Opik Cloud öffnet sich der Browser zur Anmeldung; der Installer wartet eine Minute darauf. Informiere den Benutzer daher vorher.

    uvx opik@latest mcp configure --ai-client claude-code --skills
    

    --ai-client akzeptiert außerdem codex, cursor, vscode und opencode. Wenn eine Opik-Instanz in ~/.opik.config gespeichert ist oder auf localhost läuft, führe den Befehl unverändert aus: --deployment legt die gespeicherte Konfiguration einschließlich des API-Schlüssels beiseite. Andernfalls füge das Flag für die in Schritt 2 genannte Opik-Instanz hinzu:

    Opik-Instanz des BenutzersHinzufügen
    Opik Cloud, www.comet.com--deployment cloud
    Open-Source-Opik--deployment local, und --url <url>, wenn sie nicht auf localhost läuft
    Selbst gehostete Comet-Plattform, /opik/ in ihrer URL--deployment self-hosted --url <url> --workspace <workspace>, mit OPIK_API_KEY in der Shell

    Schlägt der Befehl fehl, etwa weil die Opik-Instanz nicht erreichbar ist, teile dem Benutzer die ausgegebene Meldung und die zu prüfenden Punkte mit, zum Beispiel VPN oder URL. Wechsle nicht zu einer anderen Opik-Instanz.

  4. Anmeldung bei Opik Cloud. Wenn der Installer meldet, dass der Server noch nicht angemeldet ist, bitte den Benutzer, claude mcp login opik-mcp oder in einer Claude Code-Sitzung /mcp auszuführen, statt den Befehl selbst auszuführen: Er wartet auf den Browser. Bei einem claude.ai-Connector erfolgt die Anmeldung über /mcp. Bei der Anmeldung wird nach einem Arbeitsbereich gefragt. Nenne den in ~/.opik.config gespeicherten, falls vorhanden.

  5. Abschließen. Teile mit, was installiert wurde und was noch zu tun ist. Nenne das Skill-Paket: die Opik-Skills, die für jedes Projekt installiert werden und dem Agenten beibringen, Opik zur Instrumentierung, Evaluierung und Fehlersuche zu verwenden. Clients laden MCP-Server und Skills beim Start einer Sitzung. Bitte den Benutzer, eine neue Sitzung zu starten und anschließend „list my Opik projects“ auszuprobieren.

Für alle Fälle gilt:

  • Bitte den Benutzer nicht, einen API-Schlüssel in den Chat einzufügen. Der gehostete Server benötigt keinen. Andernfalls verwende den Schlüssel aus der Shell-Umgebung ("$OPIK_API_KEY") oder lass den Benutzer den Befehl selbst ausführen.

  • Rate nicht, welcher Arbeitsbereich verwendet wird. Er ist das Segment nach comet.com/opik/ (oder /opik/ bei einer selbst gehosteten Comet-Plattform) in der Opik-URL des Benutzers.

  • Gib ~/.claude.json oder ~/.opik.config nicht aus: Beide können API-Schlüssel enthalten. uvx opik@latest mcp status und claude mcp list zeigen die benötigten Informationen an, und der Installer liest die Konfiguration selbst aus.

  • Wenn eine Berechtigungsprüfung einen Befehl blockiert, umgehe sie nicht. Gib dem Benutzer den auszuführenden Befehl (in Claude Code muss er vor der Ausführung in der Eingabeaufforderung !). Für einen Client, den das Installationsprogramm nicht kennt, registrieren Sie ihn manuell mit den Befehlen unter Manuell einrichten: den gehosteten Server für Opik Cloud, den lokalen Server für alle anderen.

  • Bevor Sie den lokalen Server registrieren, führen Sie ihn mit der Umgebung aus, die Sie übergeben werden, und --check, wobei OPIK_API_KEY in der Shell exportiert und nicht im Befehl angegeben wird: OPIK_URL=http://localhost:5173/api uvx opik-mcp@latest --check. Der Prozess wird mit Exitcode 0 beendet und nennt den erkannten Workspace oder gibt an, was korrigiert werden muss. Nach der Registrierung meldet Claude Code „Connected“, selbst wenn der Schlüssel falsch ist, und Codex bietet keine Prüfung.

  • Claude Code weigert sich, einen vorhandenen Eintrag opik-mcp zu überschreiben. Entfernen Sie ihn daher zuerst mit claude mcp remove opik-mcp --scope user; Codex' add ersetzt ihn.

  • Lesen Sie nach der Registrierung in Claude Code nur die Statuszeile: claude mcp get opik-mcp | grep Status. Die vollständige Ausgabe gibt den Block env aus, einschließlich des API-Schlüssels. Beim gehosteten Server wird ! Needs authentication angezeigt, bis claude mcp login opik-mcp ausgeführt wurde. Bei Codex gibt es nichts, womit der Server vor einer Sitzung gestartet wird; codex mcp get opik-mcp zeigt die gespeicherten Werte an, wobei Umgebungsvariablen maskiert sind.


Manuell einrichten (ohne Opik-Prüfung, ohne Skill-Paket)

Der Befehl Schnellstart erledigt all dies für Claude Code, Codex, Cursor, VS Code Copilot und opencode und prüft außerdem, welches Opik Sie verwenden, und installiert das Skill-Paket. Registrieren Sie den Server nur für einen anderen Client manuell oder wenn Sie sehen möchten, was das Installationsprogramm schreibt. Ein Coding-Agent, der für einen Benutzer installiert, führt das Installationsprogramm aus: siehe Mit einem Coding-Agent installieren.

Gehosteter Server (Opik Cloud)

Claude Code, manuell

claude mcp add --scope user --transport http opik-mcp https://www.comet.com/opik/api/v1/mcp

Melden Sie sich anschließend in einer Claude-Code-Sitzung über /mcp → Authenticate an. Dabei wird ein Browser geöffnet, sodass die Person an der Tastatur den Vorgang ausführt. Im eigenen Terminal führt claude mcp login opik-mcp dasselbe aus. Mit --scope user ist der Server in jedem Projekt verfügbar; ohne diese Option registriert Claude Code ihn nur für das aktuelle Verzeichnis. Über SSH gibt claude mcp login opik-mcp --no-browser die Anmelde-URL aus, die Sie auf Ihrem eigenen Rechner öffnen. Für den letzten Schritt ist ein interaktives Terminal erforderlich (ssh -t).

Codex, manuell

codex mcp add opik-mcp --url https://www.comet.com/opik/api/v1/mcp

add öffnet die Anmeldung; codex mcp login opik-mcp öffnet sie erneut. In ~/.codex/config.toml sieht derselbe Server so aus:

[mcp_servers.opik-mcp]
url = "https://www.comet.com/opik/api/v1/mcp"

Cursor, manuell

Verwenden Sie die Schaltfläche unter dem gehosteten Server oder fügen Sie Folgendes zu ~/.cursor/mcp.json hinzu:

{
  "mcpServers": {
    "opik-mcp": {
      "url": "https://www.comet.com/opik/api/v1/mcp"
    }
  }
}

VS Code Copilot, manuell

Verwenden Sie die Schaltfläche unter dem gehosteten Server oder fügen Sie Folgendes zu .vscode/mcp.json in Ihrem Workspace oder zu Ihrer Benutzerkonfiguration mcp.json hinzu (MCP: Open User Configuration):

{
  "servers": {
    "opik-mcp": {
      "type": "http",
      "url": "https://www.comet.com/opik/api/v1/mcp"
    }
  }
}

Andere Clients

Jeder Client, der eine URL akzeptiert, kann den gehosteten Server verwenden:

npx add-mcp https://www.comet.com/opik/api/v1/mcp --name opik-mcp

Ein Client, der nur lokale Befehle starten kann, erreicht ihn über npx -y mcp-remote https://www.comet.com/opik/api/v1/mcp.

Opik Cloud mit einem API-Schlüssel

Wenn niemand die Browser-Anmeldung abschließen kann, etwa wenn ein Agent unbeaufsichtigt über ein Skript ausgeführt wird oder ein Client MCP OAuth nicht unterstützt, verwenden Sie stattdessen einen API-Schlüssel von comet.com/api/my/settings/, und richten Sie den lokalen Server auf Opik Cloud aus:

claude mcp add --scope user opik-mcp \
  --env OPIK_API_KEY="$OPIK_API_KEY" \
  --env OPIK_WORKSPACE=<workspace> \
  -- uvx opik-mcp

Die anderen Clients verwenden dieselben beiden Variablen in ihrem Block env. Setzen Sie OPIK_WORKSPACE auf den Abschnitt nach comet.com/opik/ in Ihrer Opik-URL (https://www.comet.com/opik/acme-ai/projects → acme-ai). Wenn der Wert fehlt, sendet der Server default, das Comet dem Standard-Workspace Ihres Kontos zuordnet. Dadurch können Lesevorgänge ohne Fehlermeldung aus dem falschen Workspace stammen.

Lokaler Server (selbst gehostetes und Open-Source-Opik)

Die Beispiele verwenden ein lokales Open-Source-Opik. Bei einem selbst gehosteten Comet ersetzen Sie die drei Variablen durch die Werte aus der Tabelle. Starten Sie nach dem Hinzufügen des Servers eine neue Sitzung und fragen Sie: „list my Opik projects“.

Claude Code, manuell

claude mcp add --scope user opik-mcp --env OPIK_URL=http://localhost:5173/api -- uvx opik-mcp

Bei einem selbst gehosteten Comet mit dem Schlüssel in der Shell-Variablen OPIK_API_KEY:

claude mcp add --scope user opik-mcp \
  --env COMET_URL_OVERRIDE=https://<host> \
  --env OPIK_WORKSPACE=<workspace> \
  --env OPIK_API_KEY="$OPIK_API_KEY" \
  -- uvx opik-mcp

Oder bearbeiten Sie ~/.claude.json direkt:

{
  "mcpServers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_URL": "http://localhost:5173/api"
      }
    }
  }
}

claude mcp get opik-mcp zeigt ✔ Connected an, sobald der Server startet. Das beweist nicht, dass URL oder Schlüssel korrekt sind, denn nur ein Tool-Aufruf erreicht Opik; --check (der lokale Server) tut dies. Außerdem gibt der Befehl den Block env aus, einschließlich des API-Schlüssels.

Codex, manuell

codex mcp add opik-mcp --env OPIK_URL=http://localhost:5173/api -- uvx opik-mcp

Oder bearbeiten Sie ~/.codex/config.toml:

[mcp_servers.opik-mcp]
command = "uvx"
args = ["opik-mcp"]
env = { OPIK_URL = "http://localhost:5173/api" }
# On a self-hosted Comet, forward the key from the environment Codex starts in,
# so it stays out of this file:
# env_vars = ["OPIK_API_KEY"]
# Time allowed for the server to start (default 10 s); the first start
# downloads the package.
startup_timeout_sec = 30

Codex übergibt einem lokalen Server nur die Variablen in env und die Namen in env_vars. Ein in Ihrer Shell exportierter Schlüssel wird daher andernfalls nicht an den Server weitergegeben.

Cursor, manuell

Fügen Sie Folgendes zu ~/.cursor/mcp.json (global) oder .cursor/mcp.json (Projekt) hinzu oder verwenden Sie Cmd+Shift+J → Features → Model Context Protocol:

{
  "mcpServers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_URL": "http://localhost:5173/api"
      }
    }
  }
}

Cursor-Zeitlimit von 60 Sekunden. Cursor erzwingt ein hartes Zeitlimit für Tool-Aufrufe, das bei Fortschrittsmeldungen nicht zurückgesetzt wird. Siehe Bekannte Host-Limits.

VS Code Copilot, manuell

Fügen Sie Folgendes zu .vscode/mcp.json in Ihrem Workspace oder zu Ihrer Benutzerkonfiguration mcp.json hinzu (MCP: Open User Configuration):

{
  "servers": {
    "opik-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["opik-mcp"],
      "env": {
        "OPIK_URL": "http://localhost:5173/api"
      }
    }
  }
}

MCP Inspector (manuelle Tests)

OPIK_URL=http://localhost:5173/api npx @modelcontextprotocol/inspector uvx opik-mcp

Sie kommen von npx opik-mcp?

Der TypeScript-Server (npm opik-mcp@2) ist veraltet und stellt am 2026-11-15 den Dienst ein. Führen Sie für eine Neuinstallation den Befehl Schnellstart aus; uvx opik-mcp ist der Befehl, mit dem ein Client den Server startet, kein Installationsprogramm. Um eine vorhandene Konfiguration für Opik Cloud zu migrieren, wechseln Sie zum gehosteten Server und entfernen Sie den API-Schlüssel. Ersetzen Sie andernfalls in Ihrer MCP-Clientkonfiguration npx -y opik-mcp durch uvx opik-mcp. Einige Umgebungsvariablen wurden umbenannt und Befehlszeilenoptionen werden nicht mehr ausgelesen: siehe den Migrationsleitfaden . Support-Richtlinie: DEPRECATED.md. Der TypeScript-Quellcode befindet sich im Git-Tag legacy-typescript-final.


Tools

opik-mcp stellt eine kleine, ergebnisorientierte Oberfläche bereit, die den gesamten Lebenszyklus abdeckt (lesen → annotieren → kuratieren → erstellen → iterieren).

ToolZweck
readUniverselles Lesen nach ID / Name / opik://-URI
listUniverselle Liste mit optionalem Namensfilter und Paginierung
writeUniverselles Schreiben — Traces/Spans protokollieren, bewerten, kommentieren, Prompts speichern, Datasets und Experimente verwalten
schemaSchemas für Schreibvorgänge untersuchen (wird vom LLM verwendet, um gültige Payloads zu erstellen)
read_skillEinen der mit diesem Server gebündelten Opik-Agent-Skills lesen

read

Ein Tool für jede Frage der Art „Zeig mir X“. Es akzeptiert ein entity_type sowie eine id (UUID oder bei benennbaren Typen einen Namen) oder eine vollständige opik://-URI. Zusammengesetzte Lesevorgänge (trace, prompt, thread, agent_insights_issue) betten ihre untergeordneten Elemente ein, sodass ein einzelner Aufruf das vollständige Bild liefert.

Der angeforderte Datensatz wird vollständig zurückgegeben. Eingebettete untergeordnete Elemente hingegen nicht: Ihre Inhalte werden mit truncate=true vom Backend abgerufen. Daher wird ein Feld mit mehr als etwa 10 KB in ClickHouse abgeschnitten und Base64-Bilder werden durch "[image]" ersetzt — andernfalls würde ein Anhang, der in 200 Spans wiederholt wird, mehr kosten als alles andere beim Lesen. Die Antwort weist unter spanBodies / messageBodies darauf hin. Jedes untergeordnete Element ist über seinen eigenen read("span", id) oder read("trace", trace_id) wieder vollständig abrufbar. Diese Aufrufe verwenden Endpunkte, die überhaupt keinen Parameter truncate haben.

Auch die Länge eingebetteter Sammlungen ist begrenzt: 200 Spans, 200 Turns, 100 Prompt-Versionen. Darüber hinaus ist spansTruncated / messagesTruncated / versionsTruncated gleich true, und eine danebenstehende Zeile moreSpans / moreMessages / moreVersions enthält die Anzahl sowie den genauen Aufruf von list(...), mit dem ab der Stelle fortgefahren wird, an der der eingebettete Teil endet.

Unterstützte Entitäten: project, trace, span, dataset, dataset_item, experiment, prompt, thread, agent_insights_issue. Die Suche nach Namen ist für project, experiment, prompt, dataset verfügbar (langsamer — zwei API-Aufrufe — und kann mehrere Treffer zurückgeben). thread und agent_insights_issue sind projektbezogen: Übergeben Sie project_id oder project_name oder einen Link/eine URI, die das Projekt enthält. dataset und dataset_item hießen früher test_suite und test_suite_item. Die alten Namen funktionieren weiterhin, werden aber nicht mehr empfohlen; neuer Code sollte die neuen Namen verwenden.

read(entity_type="trace", id="7f2e3c8a-…")
read(entity_type="project", id="demo")  # name lookup
read(entity_type="trace", id="opik://traces/7f2e3c8a-…")
read(entity_type="agent_insights_issue", id="<issue-uuid>", project_id="<project-uuid>")
read(
    entity_type="agent_insights_issue",
    id="https://www.comet.com/opik/<ws>/projects/<pid>/diagnostics?issue=<id>",
)

Ein aus der Opik-Benutzeroberfläche kopierter Link funktioniert als id: Ein Thread-Link oder ein Link zur Diagnostics-Seite enthält das Projekt, sodass project_id nicht erforderlich ist und der Entitätstyp aus dem Link übernommen wird.

Ein Lesevorgang für project beantwortet mit einem einzigen Aufruf die Frage „Wie läuft mein Projekt?“. Er gibt {project, summary, vocabulary, contains, url} zurück: den Datensatz und anschließend die vier Kennzahlen, die auf der Logs-Seite als Karten angezeigt werden (Trace-Anzahl, Fehlerrate, durchschnittliche Dauer, Gesamtkosten) für die letzten 7 Tage im Vergleich zu den 7 Tagen davor, nur SDK-Traffic, wie auf dem Bildschirm. since / until verschieben dieses Zeitfenster; since="30d" ist der Standardwert der Benutzeroberfläche. Eine Rate oder ein Durchschnitt für einen Zeitraum ohne Traces wird als null zurückgegeben, denn 0 % Fehler in einer Woche ohne Traffic würden fälschlich wie eine erfolgreiche Woche wirken.

vocabulary ist die Übersicht, die Sie brauchen, bevor Sie andere Fragen stellen können: die Namen der Feedback-Scores des Projekts, seine Token-Nutzungsschlüssel und die Automatisierungsregeln, die seine Traces bewerten. Diese Namen werden in Filtern oder in series= weiter unten verwendet. Wenn Sie sie erraten, erhalten Sie eine leere Seite, die wie eine gute Nachricht aussieht. Die Anzahl der Score-Namen und Regeln ist begrenzt; die tatsächliche Gesamtzahl wird immer angegeben und der Aufruf zum Abrufen der übrigen Einträge genannt. Die Nutzungsschlüssel werden vollständig aufgelistet, da es keine andere Möglichkeit gibt, sie abzurufen. contains nennt das neueste Experiment, Dataset, die neueste Prompt-Version und den neuesten Optimierungslauf, sodass die Frage „Was ist hier passiert?“ nicht vier weitere Aufrufe erfordert. Wenn ein Teil nicht geladen werden konnte, wird dies angegeben, statt ihn leer erscheinen zu lassen; leere Teile werden ausgelassen.

Ein Lesevorgang für agent_insights_issue gibt {issue, example_trace_ids, details} zurück: den Diagnostics-Eintrag (Name, Beschreibung, Ursache, Lösungsvorschlag, Schweregrad, Status), die deduplizierten IDs der Traces, bei denen das Problem auftritt (dieselbe Stichprobe, die auf der Diagnostics-Seite angezeigt wird — öffnen Sie einen davon mit read("trace", id)), sowie die Aufschlüsselung nach Tagen. Trace-Inhalte werden nicht eingebettet, sodass der Lesevorgang bei einem Backend-Aufruf bleibt. since / until grenzen die Tageszeilen ein; standardmäßig wird der gesamte Zeitraum verwendet. Wenn dem Server die Opik-URL und der Workspace der Sitzung bekannt sind, enthält der Lesevorgang außerdem url (die Diagnostics-Seite des Problems) und trace_url_template (einen Deeplink zu einem beliebigen Beispiel-Trace), sodass der Assistent Ihnen einen anklickbaren Link geben kann. Bei einer OAuth-Sitzung, deren Workspace nicht ermittelt werden konnte, werden die Links weggelassen, statt geraten.

Traces selbst enthalten keine URL — ein Link zu einem Trace lässt sich nicht aus den Feldern ableiten, die ein read oder list zurückgibt, und eine erratene URL führt zu einem 404-Fehler. Die Sitzungsanweisungen geben stattdessen eine Vorlage dafür an, .../v1/session/redirect/projects/?trace_id={trace_id}&path=..., sodass der Assistent eine ID einsetzt und Ihnen einen Link bereitstellt. Der Link führt über die Weiterleitung von opik-backend, die Projekt und Workspace anhand des Traces ermittelt. Daher funktioniert er auch dort, wo eine direkte Projekt-URL nicht funktioniert, einschließlich einer OAuth-Sitzung mit nicht aufgelöstem Workspace. Es ist derselbe Link, den das Python-SDK für einen Trace ausgibt.

list

Eine Sammlung mit Paginierung durchsuchen oder filtern. Projektbezogene Typen (trace, span, thread, agent_insights_issue, dataset_item, prompt_version) benötigen ihr übergeordnetes Element: eine Projekt-UUID oder einen Projektnamen, eine Dataset-UUID oder eine Prompt-UUID.

list(entity_type="experiment", page=1, size=25)
list(entity_type="experiment", name="rerank")  # name substring filter
list(entity_type="agent_insights_issue", project_name="demo")  # open Diagnostics issues
list(entity_type="agent_insights_issue", project_id="<uuid>", status="resolved")
list(entity_type="trace", project_name="demo")  # latest traces of one project
list(
    entity_type="trace", project_name="demo", filters="error_info is_not_empty AND duration > 5000"
)
list(
    entity_type="span",
    project_name="demo",  # spans across the whole project
    filters='type = "llm" AND usage.total_tokens > 10000',
)
list(
    entity_type="thread",
    project_name="demo",
    filters="number_of_messages > 20 AND feedback_scores.helpfulness < 0.5",
)
list(entity_type="experiment", filters='dataset_id = "<dataset-uuid>" AND tags contains "baseline"')

Filter. trace, span, thread, experiment und dataset_item akzeptieren einen OQL-String mit derselben Grammatik wie search_traces(filter_string=…) des SDK:

<field>[.<key>] <op> <value> [AND ...]
ops: = != > >= < <= contains not_contains starts_with ends_with is_empty is_not_empty in not_in

Zeichenfolgen stehen in doppelten Anführungszeichen, Zahlen ohne Anführungszeichen, duration wird in Millisekunden angegeben, Datumsangaben sind ISO-8601-Zeitpunkte mit Zeitzone ("2026-09-08T10:00:00Z"). Scores und Dictionaries benötigen einen Schlüssel: feedback_scores.accuracy < 0.5, metadata.environment = "prod". AND ist der einzige Connector.

Wie auf der Logs-Seite der UI fügen Trace-, Span- und Thread-Listen source = "sdk" hinzu, damit Evaluator-, Playground- und Experiment-Traces nicht im Weg sind; benenne source selbst, um sie zu sehen. Die erste Ausgabezeile gibt den angewendeten Filter wieder.

Ein ungültiger Filter schlägt fehl, bevor er das Backend erreicht, und nennt, was zu seiner Korrektur nötig ist: die Position eines Syntaxfehlers, den ähnlichsten Feldnamen, die gültigen Operatoren für den Feldtyp oder das erwartete Werteformat. Auch Felder mit einer abgeschlossenen Wertemenge (source, Span type, Thread status, visibility_mode) werden dagegen geprüft, einschließlich jedes Elements einer in-Liste. source ist das einzige Feld, das das Backend selbst validiert. Bei einem unbekannten Wert antwortet es mit 500 statt mit 400, sodass source = "SDK" bei einem Großbuchstaben andernfalls einen undurchsichtigen Serverfehler verursachen würde. Der Rest wird als Zeichenfolge verglichen und liefert eine leere Seite, was wie „keine Treffer“ aussieht, obwohl es „kein solcher Wert“ bedeutet. Frage schema("list.trace") (oder list.span, list.thread, list.experiment) nach der vollständigen Feldreferenz, einschließlich der akzeptierten Werte.

Einen Fall in einem Dataset finden. list(entity_type="dataset_item", dataset_id=…) filters on the case itself: data.<key> für die Schlüssel, mit denen das Dataset erstellt wurde, full_data für eine Teilzeichenfolge der gesamten Nutzlast (ein vollständiger Scan — gib nach Möglichkeit einen Schlüssel an), außerdem id, tags, source, trace_id, span_id und die Zeitstempel. data.<key> akzeptiert nur die sechs Zeichenfolgenoperatoren (=, !=, contains, not_contains, starts_with, ends_with); das Backend antwortet auf einen Vergleich mit 400, daher wird dieser vor dem Aufruf abgelehnt. Der Endpunkt bietet weder Sortierung noch Freitextsuche — sort wird abgelehnt, statt ignoriert zu werden. read(entity_type="dataset_item", id=…) gibt einen Fall vollständig zurück. So lässt sich ein Wert wieder abrufen, den die Tabelle abgeschnitten hat.

list(entity_type="dataset_item", dataset_id="<uuid>", filters='data.question contains "install"')
list(
    entity_type="dataset_item", dataset_id="<uuid>", filters='trace_id = "<trace-uuid>"'
)  # the case made from that trace
read(entity_type="dataset_item", id="<item-uuid>")  # the case, uncut

Mit experiment_ids ist dieselbe Liste stattdessen der Vergleich — die Fälle mit angehängtem Lauf — und sie filtert nach den Läufen (feedback_scores.<name>, output, duration). Es handelt sich um unterschiedliche Feldmengen auf zwei Backend- Endpunkten: schema("list.dataset_item_case") sind die eigenen Fälle des Datasets, schema("list.dataset_item") der Vergleich.

Sortierung. trace, span, thread und experiment akzeptieren sort="<field> [asc|desc]", standardmäßig desc, und jeweils nur ein Feld: sort="duration desc", sort="total_estimated_cost", sort="feedback_scores.accuracy asc", sort="usage.total_tokens". Das Feld wird vor dem Aufruf mit der sortierbaren Liste der Entität abgeglichen, da das Backend Felder, nach denen es nicht sortieren kann, stillschweigend ignoriert. In sehr großen Workspaces lässt das Backend die Sortierung vollständig weg; die Kopfzeile weist darauf hin, wenn das passiert.

dataset_item sortiert nur als Vergleich (mit experiment_ids): Der Items-Endpunkt akzeptiert keinen Sortierparameter, daher wird eine Sortierung in einer einfachen Auflistung abgelehnt, statt ignoriert zu werden.

Zeitfenster und Suche. trace, span und thread akzeptieren since und until, jeweils eine relative Zeitspanne ("30m", "1h", "7d") oder einen ISO-8601-Zeitpunkt mit Zeitzone, sodass „die letzte Stunde“ keine Zeitberechnung erfordert. Das Zeitfenster richtet sich nach dem Erstellungszeitpunkt des Datensatzes. Das ist für das Backend kostengünstig und stimmt bei Live-Traffic innerhalb von Sekunden mit start_time überein. Für eine exakte Grenze setze start_time in filters. Dieselben drei Typen akzeptieren search, Freitext, der an beliebiger Stelle in ID, Name, Eingabe, Ausgabe, Metadaten, Tags und Thread-ID gefunden wird. Die Suche durchsucht das gesamte Projekt im Backend, daher kann der erste Aufruf bei einem großen Projekt mehrere zehn Sekunden dauern. Für diese Aufrufe gilt ein Timeout von 60 Sekunden. Mit since werden sie wieder schnell.

Tabelle lesen. Dauern sind mit duration_ms / ttft_ms beschriftet und werden als ganze Millisekunden angezeigt; das Feld bleibt duration in filters und sort. Zeitstempel werden sekundengenau und Kosten als einfache Dezimalzahlen angezeigt. Projektzeilen enthalten last_updated_trace_at, damit du siehst, in welchem Projekt Live-Traffic eingeht; Thread-Zeilen enthalten die erste Nachricht. Eine leere Seite innerhalb eines Zeitfensters gibt an, wann der letzte Trace des Projekts eingegangen ist. Eine leere Seite unter dem Standardwert source = "sdk" erklärt, wie du die anderen Quellen anzeigen kannst. Ein falsch geschriebenes project_name wird mit dem ähnlichsten vorhandenen Namen zurückgegeben.

list(
    entity_type="trace",
    project_name="demo",
    since="1h",
    filters="error_info is_not_empty",
    sort="duration desc",
)
list(entity_type="trace", project_name="demo", search="order-42")

Diagnoseprobleme. agent_insights_issue ist die Diagnostics-Seite über MCP: die wiederkehrenden Fehler, die der Diagnostics-Job von Opik für ein Projekt gruppiert hat, sortiert wie in der UI (zuletzt aufgetretene zuerst). Die Spalten sind severity, status, total_occurrences (Gesamtsumme), latest_count (der jüngste Berichtstag, auf den sich die Beschreibung des Problems selbst bezieht) und last_seen. Standardmäßig werden offene Probleme aufgelistet; übergib status="resolved" oder "closed" für die übrigen. read und list werden auch als issue bezeichnet, wie die UI diese nennt; der lange Name ist der Eintrag in der entity_type-Enum, damit diese Entität dort nicht zweimal erscheint. Die Zählungen beziehen sich auf den gesamten Zeitraum, damit sie mit der UI übereinstimmen; dieselben since / until wie bei Traces grenzen das Zeitfenster ein, das auf UTC-Berichtstage gekürzt wird, da Diagnostics nach Tagen aggregiert.

Eine leere Liste erklärt, warum sie leer ist, denn „nichts ist kaputt“ und „niemand hat Diagnostics aktiviert“ sehen andernfalls gleich aus. Es gibt fünf Zustände: Diagnostics ist in dieser Bereitstellung nicht verfügbar, für dieses Projekt nicht aktiviert, ausgeschaltet, aktiviert, aber seit Kurzem nicht gescannt, oder aktiviert und fehlerfrei, mit dem Zeitpunkt des letzten Scans. Die Zustände, bei denen du etwas tun kannst, nennen den erforderlichen Aufruf, und jeder Zustand verlinkt auf die Diagnostics-Seite des Projekts.

Eine nicht leere Liste gibt ihren Zeitraum selbst an. Die Probleme entsprechen den Gruppen des letzten Scans, daher endet die Antwort mit Report covers data through <time>. Wenn das angefragte Zeitfenster darüber hinausreicht, wird die nicht abgedeckte Zeitspanne genannt und erklärt, wie sie abgedeckt werden kann: durch einen Trigger, sobald ein erneuter Scan weit genug zurückreicht, andernfalls durch rohe Traces mit dem angegebenen since. Wenn du für ein Projekt, das jede Nacht gescannt wird, eine Woche anfragst, fehlt der letzte Tag in der gruppierten Antwort; hier wird darauf hingewiesen.

write("agent_insights_job.enable", {"project_name": "demo"}) aktiviert Diagnostics. Ab dann werden täglich Scans ausgeführt, und ein erneuter Aufruf ist unbedenklich. write("agent_insights_job.trigger", …) scannt jetzt die letzten 24 Stunden, ohne auf den nächtlichen Lauf zu warten. Beide erfordern dieselbe Berechtigung wie das Lesen von Problemen, und beide werden abgelehnt, wenn Diagnostics in der Bereitstellung nicht verfügbar ist.

Ein Problem durchläuft seinen Lebenszyklus mit write("agent_insights_issue.resolve", {"issue_id": "<uuid>", "project_name": "demo"}) — erledigt — oder …close für eines, bei dem sich Maßnahmen nicht lohnen, und mit …reopen, um beide wieder in die Liste der offenen Probleme aufzunehmen. Alle drei erfordern dieselbe Berechtigung und antworten mit einem Link zur Ansicht, in die das Problem verschoben wurde, da ein gelöstes Problem nicht mehr auf der Standardseite erscheint. Ob ein Fehler behoben ist, ist eine Ermessensentscheidung. Daher sind diese Aktionen für den Fall gedacht, dass du sie anforderst: Der Assistent sollte die Liste nicht eigenmächtig aufräumen, während er Probleme untersucht.

Metriken im Zeitverlauf. project_metric stellt eine Metrik für ein Projekt als Tabelle mit Zeitintervallen dar: Trace-, Span- und Thread-Anzahlen, Dauern, Fehlerraten, Kosten, Token-Nutzung und Feedback-Scores. Damit beantwortet es die Frage, die sich an die Übersicht anschließt: wann sich etwas geändert hat.

list(entity_type="project_metric", project_name="demo", metric_type="trace_count")
list(
    entity_type="project_metric",
    project_name="demo",
    metric_type="trace_error_rate",
    since="14d",
    interval="daily",
)
list(
    entity_type="project_metric", project_name="demo", metric_type="span_count", breakdown="model"
)  # one column per model
list(
    entity_type="project_metric",
    project_name="demo",
    metric_type="span_duration",
    breakdown="model",
    series="p99",
)  # the p99 of each model

Die Zeilen sind Zeitintervalle, keine Datensätze. Daher werden page, size und sort abgelehnt, statt ignoriert zu werden. interval ist hourly, daily, weekly oder total; wenn nicht angegeben, richtet es sich wie im Metrics-Tab nach dem Zeitfenster — stündlich bis zu 3 Tagen, täglich bis zu 30, wöchentlich darüber hinaus. So umfasst ein Standarddiagramm unabhängig vom Zeitraum einige Dutzend Zeilen, während ein stündlicher Monat (721 Zeilen) ausdrücklich angefordert werden muss. since / until akzeptieren dieselben Formate wie überall sonst und verwenden standardmäßig die letzten 7 Tage. filters verwendet die Felder der Entität, auf die sich die Metrik bezieht. Eine Span-Metrik wird also nach Span-Feldern gefiltert.

breakdown unterteilt jedes Zeitintervall nach tags, name, error_info, error_type, model, provider, span_type, guardrail_name oder metadata.<key>. Nicht jede Metrik akzeptiert alle diese Optionen, und sieben akzeptieren gar keine. Das Tool weiß, welche Optionen gültig sind, und teilt dies vor dem Aufruf des Backends mit. Falls vorhanden, nennt es eine Metrik, die dieselbe Frage beantwortet. Drei Familien liefern mehrere Zeitreihen auf einmal zurück (eine Dauer als p50/p90/p99, einen Feedback-Score pro Name, Token-Nutzung pro Schlüssel). Beim Gruppieren stellt das Backend jeweils nur eine davon dar, daher wählt series= sie aus: ein Perzentil, einen Score-Namen oder einen Nutzungsschlüssel. Für die Dauer gilt standardmäßig p50, für die Token-Nutzung total_tokens; der jeweils verwendete Wert wird in der ersten Zeile wiedergegeben.

Leere Zeitintervalle werden ausgelassen und darunter gezählt. So besteht ein ruhiger Monat aus wenigen Zeilen statt einer Spalte voller Nullen, und eine Rate für ein Zeitintervall ohne Traces fehlt, statt als null angegeben zu werden.

Frage schema("list.project_metric") nach der Metriktabelle, den Intervallen und der Gruppierungsmatrix pro Metrik.

Die Namen eines Projekts. score_name listet die in einem Projekt erfassten Feedback-Score-Namen auf und online_rule die dafür konfigurierten Evaluatoren für Automatisierungsregeln, aus denen die meisten dieser Namen stammen. Beide entsprechen denselben Listen, die read("project", …) vollständig und paginiert bereitstellt, falls die begrenzte Version in der Übersicht nicht ausreicht.

list(entity_type="score_name", project_name="demo")
list(entity_type="online_rule", project_name="demo")

write

Universeller Dispatcher für Schreibvorgänge. Übergib operation + data, und der Dispatcher validiert die Nutzlast, wendet die passende REST-Methode an und gibt die Backend-Antwort zurück.

Operationen:

OperationBeschreibung
trace.createEinen einzelnen Trace (oder einen Batch) protokollieren. Übergeordneter Eintrag für Spans / Scores / Kommentare.
trace.updateEinen vorhandenen Trace abschließen oder ändern.
span.createEinen Span in einem vorhandenen Trace protokollieren (oder einen Batch).
score.createEinen numerischen Feedback-Score an einen Trace, Span oder Thread anhängen.
comment.createEinen Freitextkommentar an einen Trace, Span oder Thread anhängen.
prompt_version.saveEine neue Prompt-Version speichern (erstellt den Prompt anhand des Namens, falls er fehlt).
dataset.createEin Dataset erstellen — type: "test_suite" macht daraus eine Testsuite für Evaluierungen.
dataset_item.upsertItems in ein Dataset einfügen oder aktualisieren (immer im Envelope-Format).
experiment.createEin auf ein Dataset beschränktes Experiment erstellen.
experiment_item.createTrace- und dataset_item-Zeilen an ein Experiment anhängen.
thread.closeEinen Thread schließen (als inaktiv markieren). Übergib thread_id und das Projekt.
thread.openEinen geschlossenen Thread wieder öffnen. Übergib thread_id und das Projekt.
agent_insights_job.enableDiagnostics für ein Projekt aktivieren (tägliche Scans, wiederholter Aufruf unbedenklich).
agent_insights_job.triggerJetzt einen Diagnostics-Scan über die letzten 24 Stunden ausführen.
agent_insights_issue.resolveEin Diagnostics-Problem als erledigt markieren (zuerst den Benutzer fragen).
agent_insights_issue.closeEin Diagnostics-Problem als nicht handlungsrelevant markieren (zuerst den Benutzer fragen).
agent_insights_issue.reopenEin gelöstes oder geschlossenes Diagnostics-Problem wieder in die Liste der offenen Probleme aufnehmen.
annotation_queue.createDie Annotationswarteschlange eines Projekts erstellen, optional mit einer benutzerdefinierten Annotator-Ansicht.
annotation_queue.updateEine Annotationswarteschlange ändern; ihre Annotator-Ansicht festlegen, ersetzen oder löschen.
write(
    operation="score.create",
    data={
        "target": "trace",
        "target_id": "7f2e3c8a-…",
        "name": "helpfulness",
        "value": 0.9,
        "reason": "great recovery",
    },
)

schema

Prüfe vor dem Aufruf die genaue JSON-Struktur und die erforderlichen Felder eines beliebigen Schreibvorgangs — nützlich, wenn du dir nicht sicher bist, wie data aussehen sollte. Gibt das Schema, den OAuth-Scope und ein validiertes Beispiel zurück. Reine Abfrage, kein Backend-Aufruf.

schema(operation="score.create")
schema(operation="prompt_version.save")

Dasselbe Tool beantwortet list.trace, list.span, list.thread und list.experiment mit der Referenz des Tools list für diese Entität: alle filterbaren Felder mit ihrem Typ und den gültigen Operatoren, die sortierbaren Felder, ob ein Zeitfenster und eine Freitextsuche unterstützt werden, sowie zwei Beispielfilter.

schema(operation="list.trace")

Konfiguration

Diese Einstellungen konfigurieren den lokalen Server; jede Einstellung ist eine Umgebungsvariable. Der gehostete Server auf Opik Cloud verwendet keine davon.

Identität / Endpunkt

VariableStandardwertHinweise
OPIK_API_KEY—API-Schlüssel für ein selbst gehostetes Comet oder für Opik Cloud ohne den gehosteten Server. Für Open-Source-Opik ist keiner erforderlich, sofern die Bereitstellung keine Authentifizierung hinzufügt.
OPIK_WORKSPACEnicht gesetztWorkspace-Name. Wird der Wert in der Cloud mit einem API-Schlüssel nicht gesetzt, sendet der Server default, wodurch der Standard-Workspace deines Kontos ermittelt wird — setze den Wert explizit, wenn du in einem anderen Workspace arbeitest, andernfalls werden Lesezugriffe unbemerkt aus dem falschen Workspace ausgeführt. Bei OAuth nicht setzen (der Token enthält den Wert) und auch nicht lokal/bei OSS (default ist dort der einzige Workspace).
COMET_WORKSPACE—Veralteter Alias für OPIK_WORKSPACE (Abwärtskompatibilität). Wenn beide gesetzt sind, hat OPIK_WORKSPACE Vorrang.
COMET_WORKSPACE_IDnicht gesetztOptionale Workspace-UUID. Wird bei gesetztem Wert in Analytics-Ereignisse eingetragen und hat Vorrang vor der ermittelten UUID. Selten erforderlich — OAuth-Installationen erhalten die UUID automatisch aus dem Token.
COMET_URL_OVERRIDEhttps://www.comet.comAuf den Host deines selbst gehosteten Comet oder für Staging auf https://dev.comet.com setzen.
OPIK_URLabgeleitet aus COMET_URL_OVERRIDE + /opik/apiFür Open-Source-Opik setzen, das seine API unter /api bereitstellt (http://localhost:5173/api lokal). Auf einer Comet-Plattform nur überschreiben, wenn Opik auf einem anderen Host/Pfad als die Comet-Benutzeroberfläche liegt.
OPIK_DEFAULT_PROJECT_NAMEnicht gesetztWenn gesetzt, weist der sitzungsbezogene instructions-Blob das LLM an, diesen Wert bei jedem Tool-Aufruf als project_name zu übergeben, sofern der Benutzer kein anderes Projekt angibt.

Server / Transport

VariableStandardwertHinweise
OPIK_MCP_TRANSPORTstdiostdio für den Start durch einen Host, streamable-http zum Lauschen an einem Port.
OPIK_MCP_HOST127.0.0.1Bind-Host von uvicorn (nur streamable-http).
OPIK_MCP_PORT8080Bind-Port von uvicorn (nur streamable-http).
OPIK_MCP_RELOADfalseAuf true setzen, um uvicorn --reload zu aktivieren (nur für die Entwicklung).
OPIK_MCP_AS_URLnicht gesetztURL des OAuth Authorization Servers, angegeben in /.well-known/oauth-protected-resource (RFC 9728) und als Proxy-Ziel für AS-Erkennungsabfragen verwendet. Erforderlich, damit MCP-Hosts den OAuth-Ablauf über HTTP starten können.
OPIK_MCP_RESOURCE_URInicht gesetztKanonische öffentliche URI dieses Servers, angegeben als resource in den Metadaten der geschützten Ressource und zur Ableitung des Hinweises WWW-Authenticate verwendet.
OPIK_MCP_OAUTH_VALIDATION_CACHE_TTL_S30Gibt an, wie lange einer „gültigen“ Antwort der Token-Introspektion von opik-backend vertraut wird, bevor die nächste Anfrage mit demselben OAuth-Token erneut nachfragt. Begrenzt die zusätzliche Backend-Last durch die Validierung jeder Anfrage und den Zeitraum, in dem ein abgelaufener Token noch weitergeleitet wird (dieser Zeitraum endet ebenfalls mit der ersten 401-Antwort des Backends). Wird durch den eigenen expires_at des Tokens begrenzt, sofern das Backend einen solchen meldet.
OPIK_MCP_LOG_LEVELINFOSchwellenwert für stderr-Logger.

Transport auswählen

Zwei Bearer-Formate, zwei Verträge für den HTTP-Transport. Ein OAuth- Zugriffstoken opik_mcp_at_… wird bei jeder Anfrage über den Token- Introspektionsendpunkt von opik-backend validiert (zwischengespeichert, siehe OPIK_MCP_OAUTH_VALIDATION_CACHE_TTL_S); ein abgelaufener oder widerrufener Token erhält eine HTTP-401-Antwort mit WWW-Authenticate: Bearer error="invalid_token", woran MCP-Hosts ihren stillen refresh_token-Grant erkennen. Ein Opik-API-Schlüssel wird nicht lokal validiert: Er wird unverändert an opik-backend weitergeleitet, wo die Durchsetzung zentral erfolgt. Wähle den Transport passend zur Bereitstellung:

SzenarioTransport
Opik CloudNichts auszuführen: der gehostete Server ist dieser Server über HTTP, betrieben von Comet
MCP-Client und Opik auf demselben Rechner (lokale OSS-Installation)stdio (empfohlen — am einfachsten, kein Port, keine OAuth-Einrichtung)
Lokaler MCP-Client → selbst gehostetes Opikstdio mit den Umgebungsvariablen für die Bereitstellung oder HTTP mit OAuth (OPIK_MCP_AS_URL verweist auf das Backend)
opik-mcp wird hinter demselben Edge wie opik-backend bereitgestelltHTTP — Bearer-Tokens werden vom Backend bei jeder Anfrage validiert

Hinweis zu lokalen OSS-Installationen: Das OSS-Backend authentifiziert keine Anfragen, daher ist ein davor geschaltetes HTTP-opik-mcp genauso offen wie die OSS-REST-API selbst. Behalte in gemeinsam genutzten Netzwerken die standardmäßige Bindung 127.0.0.1 bei (und bevorzuge stdio).

Telemetrie

VariableStandardwertHinweise
OPIK_MCP_ANALYTICS_ENABLEDtrueAuf false setzen, um die gesamte Telemetrie außer Sentry zu deaktivieren.
`OPIK_MCP_SENTRY_ENABLEDtrueSet to false zum Deaktivieren der gesamten Sentry-Telemetrie.
=======

Bekannte Host-Limits

Hosts unterscheiden sich darin, wie lange sie einen einzelnen Tool-Aufruf laufen lassen:

  • Claude Code — kein dokumentiertes Timeout für Tool-Aufrufe. Empfohlen.
  • Cursor — hartes Timeout von 60 s, das sich bei Fortschritt nicht zurücksetzt (Upstream-Bug).
  • MCP Inspector — MAX_TOTAL_TIMEOUT begrenzt die Gesamtdauer (Standard: 60 s). Erhöhe den Wert in der Inspector-Benutzeroberfläche für längere Vorgänge.

Wenn ein Aufruf hängen bleibt, setze OPIK_MCP_LOG_LEVEL=DEBUG, um das vollständige Anfrageprotokoll zu erhalten.


Fehlerbehebung

Funktioniert die Einrichtung? Starte den Server mit den Umgebungsvariablen aus der Client-Konfiguration und --check: OPIK_URL=http://localhost:5173/api uvx opik-mcp@latest --check. Der Befehl nennt den Workspace und die darin gefundenen Projekte oder gibt an, was zu korrigieren ist. Auch die Fehlermeldungen des Servers nennen die erforderlichen Änderungen und verweisen auf die entsprechende Dokumentationsseite.

OPIK_API_KEY wird nicht übernommen — die Variable erreicht den Serverprozess nicht. In Claude Code / Cursor / VS Code gelten Umgebungsvariablen nur innerhalb des env-Blocks der MCP-Serverkonfiguration, nicht in deiner Shell; Codex leitet außerdem die in env_vars aufgeführten Namen weiter. Starte nach Änderungen eine neue Sitzung, da Clients die Konfiguration beim Sitzungsstart einlesen.

Anfragen gehen bei Open-Source-Opik an /opik/api — COMET_URL_OVERRIDE ist für eine selbst gehostete Comet-Plattform vorgesehen. Open Source stellt seine API unter /api bereit: Setze stattdessen OPIK_URL=http://localhost:5173/api (oder https://<host>/api). Der Server warnt beim Start davor, wenn der Host dieser Rechner ist, und --check antwortet mit „No Opik API at …“.

Cursor-Aufruf läuft nach 60 s ab — ein bekannter Cursor-Bug, kein Problem mit opik-mcp. Entweder den Aufruf eingrenzen (kleineres size, kürzeres Zeitfenster) oder denselben Vorgang in Claude Code ausführen, das kein hartes Limit hat.

Server wird nicht angezeigt, Anmeldung öffnet sich nicht, falscher Workspace, uvx nicht gefunden. Diese Fälle werden im Abschnitt zur Fehlerbehebung in der Dokumentation behandelt. uvx opik@latest mcp status listet alle Clients auf, bei denen der Server konfiguriert ist, und zeigt an, ob ihre Konfiguration abweicht.


Entwicklung

git clone git@github.com:comet-ml/opik-mcp.git
cd opik-mcp
make install        # uv sync --locked --extra dev
make check          # lint + typecheck + test
make run-dev        # uvicorn with --reload + DEBUG logs
make inspect        # MCP Inspector against the running server

Häufige Ziele:

ZielFunktion
make installuv sync --locked --extra dev
make runMCP-Server ausführen (standardmäßig stdio).
make run-devMit DEBUG-Protokollierung + uvicorn --reload ausführen.
make devÜber mcp dev ausführen (Inspector-Wrapper für den Entwicklungsmodus).
make inspectMCP Inspector mit einem laufenden Server starten.
make testuv run pytest -q.
make lintruff check + Formatprüfung.
make formatruff format + ruff check --fix.
make typecheckmypy.
make checklint + typecheck + test.

Repository-Struktur:

opik-mcp/
├── src/opik_mcp/        ← server, tools, analytics
├── tests/               ← pytest suites
├── scripts/             ← live-BE smoke + MCP-session smoke
├── legacy/typescript/   ← migration guide for the deprecated v2 TS server (source: tag `legacy-typescript-final`)
├── pyproject.toml
└── Makefile

Hilfe erhalten


Lizenz

Apache-2.0.