Comet Opik
officielInterrogez et analysez vos logs Opik, traces, prompts et toutes autres données de télémétrie de vos LLMs en langage naturel.
Que pouvez-vous faire avec Comet Opik MCP ?
- Interroger les traces par projet — Demandez quelles traces d’un projet ont échoué aujourd’hui, avec des filtres sur les informations d’erreur, la durée ou l’utilisation des jetons.
- Lire n’importe quelle entité Opik — Récupérez un projet, une trace, un span, un jeu de données, une expérience, un prompt, un fil de discussion ou un problème de Diagnostics par identifiant, nom ou URI
opik://. - Enregistrer des scores et des commentaires — Attribuez un score à une trace selon une métrique de feedback avec un motif, ou ajoutez des commentaires via l’outil d’écriture.
- Enregistrer des versions de prompts — Créez et stockez de nouvelles versions de prompts avec les jeux de données et les expériences.
- Examiner les schémas d’écriture — Demandez le schéma d’une opération d’écriture pour créer une charge utile valide avant de l’envoyer.
- Vérifier l’état du projet — Consultez un projet pour obtenir le nombre de traces, le taux d’erreur, la durée moyenne et le coût total des 7 derniers jours.
Documentation
Serveur MCP Opik
Le serveur officiel Model Context Protocol (MCP) pour Opik, la plateforme open source d’observabilité et d’évaluation des LLM, créée par Comet. Connectez directement votre hôte IA (Claude Code, Cursor, VS Code Copilot, Codex, opencode ou tout client MCP) à votre espace de travail Opik : consultez les traces, consignez les scores et enregistrez les versions des prompts, le tout depuis le chat.
Conçu pour les ingénieurs LLM qui utilisent déjà Opik et souhaitent le piloter depuis le même assistant IA que celui avec lequel ils codent.
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
Démarrage rapide
Une seule commande configure Opik dans les clients IA de votre machine, y compris Claude Code. Elle détecte votre instance Opik (celle enregistrée dans ~/.opik.config, une instance exécutée sur localhost, ou vous demande laquelle choisir), enregistre le serveur MCP, installe le pack de compétences Opik et vérifie la connexion. Avec Opik Cloud, aucune clé API n’est à gérer : votre client vous connecte dans le navigateur. Il faut uv et aucun SDK Opik :
uvx opik@latest mcp configure
Sans terminal, par exemple depuis un agent de programmation ou un script, indiquez le client :
uvx opik@latest mcp configure --ai-client claude-code --skills
--ai-client accepte également codex, cursor, vscode et opencode. Dans ce cas, la commande utilise l’instance Opik enregistrée dans ~/.opik.config, clé API comprise, ou une instance qui répond sur localhost ; sinon, elle s’arrête et demande --deployment.
Un agent de programmation à qui l’on demande « install opik mcp » obtient toutes les étapes, y compris les questions à poser à l’utilisateur, depuis uvx opik-mcp@latest --help. Elles sont identiques à celles de la section Installation avec un agent de programmation ci-dessous.
L’enregistrement manuel du serveur, avec les commandes client de la section Configuration manuelle, ignore la vérification de l’instance Opik utilisée et l’installation du pack de compétences ; cette méthode est donc destinée aux clients non pris en charge par l’installateur.
| Votre instance Opik | Serveur | Transport | Connexion |
|---|---|---|---|
Opik Cloud (www.comet.com) | le serveur hébergé, géré par Comet | Streamable HTTP | dans le navigateur (OAuth) ; aucune clé API |
| Comet auto-hébergé, Opik open source | le serveur local, ce package | stdio | variables d’environnement ; une clé API uniquement si le déploiement l’exige |
Les clients chargent les serveurs MCP au démarrage d’une session ; démarrez donc une nouvelle session ensuite.
Guide de configuration, dépannage et FAQ : comet.com/docs/opik/mcp-server.
Opik Cloud : le serveur hébergé
Comet gère le serveur à l’adresse https://www.comet.com/opik/api/v1/mcp. Votre client s’y connecte par HTTP et ouvre une page de connexion dans le navigateur la première fois. Rien à installer, aucune clé API ni aucun espace de travail à configurer : le serveur fonctionne dans l’espace de travail choisi lors de la connexion. Après l’avoir ajouté, démarrez une nouvelle session et demandez : « liste mes projets Opik ».
La commande de Démarrage rapide configure le serveur pour Claude Code, Codex, Cursor, VS Code Copilot et opencode, avec le pack de compétences. Dans Claude Code, le plugin fait la même chose en une seule commande. Les boutons ci-dessous permettent de l’ajouter à Cursor ou VS Code en un clic ; les autres méthodes d’enregistrement manuel sont décrites dans Configuration manuelle.
Plugin Claude Code
Le plugin opik installe les compétences Opik et enregistre le serveur MCP hébergé pour Opik Cloud :
/plugin install opik --marketplace comet-ml/opik-mcp
Avec une version de Claude Code antérieure à 2.1.275, exécutez /plugin marketplace add comet-ml/opik-mcp, puis /plugin install opik@opik. Les compétences se chargent sous la forme opik:<skill>, par exemple opik:opik-instrument, et /mcp affiche le serveur sous le nom plugin:opik:opik-cloud. Il s’agit du serveur d’Opik Cloud. Démarrez une nouvelle session, puis connectez-vous depuis /mcp → Authenticate. Pour une instance Comet auto-hébergée qui exécute le serveur OAuth MCP, ajoutez-la avec claude mcp add --transport http opik-mcp https://<host>/opik/api/v1/mcp ; pour toute autre instance Opik auto-hébergée ou open source, utilisez la commande de Démarrage rapide. Désactivez ensuite plugin:opik:opik-cloud dans /mcp. Claude Code ne met pas automatiquement à jour un plugin provenant de cette marketplace : exécutez /plugin marketplace update opik, puis /plugin update opik@opik, ou activez la mise à jour automatique de la marketplace dans /plugin. Cette marketplace fournit main, qui peut être plus récent que la dernière version publiée. Une mise à jour n’est disponible qu’à chaque publication, lorsque la version du plugin change.
Si vous aviez déjà ajouté opik-mcp à la même URL, Claude Code conserve votre copie et ignore celle du plugin. Si votre entrée correspond à un autre serveur, comme le serveur local uvx opik-mcp, les deux sont chargés : exécutez claude mcp remove opik-mcp pour ne conserver que celui du plugin. Les compétences du pack se chargent également à côté des copies du plugin ; supprimez-les avec npx skills remove --global --agent claude-code, qui vous demandera lesquelles.
Opik auto-hébergé et open source : le serveur local
opik-mcp s’exécute sur votre machine : le client le démarre avec uvx opik-mcp et communique avec lui via stdio. La commande de Démarrage rapide le configure à partir de votre ~/.opik.config ou d’une instance Opik locale ; pour l’enregistrer manuellement, consultez Configuration manuelle. Installez uv une seule fois ; au premier lancement, cet outil récupère le package et Python 3.13 si nécessaire :
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
# or: brew install uv
uvx opik-mcp réutilise la copie mise en cache par uv, ce qui accélère le démarrage ; uv cache clean opik-mcp fait récupérer la dernière version au prochain démarrage. uvx opik-mcp@latest interroge PyPI à chaque démarrage, ce qui ajoute environ une seconde et demie. Codex attend mcp_optional_startup_grace_ms (1 s par défaut) que les serveurs démarrent avant de créer la première liste d’outils ; un démarrage plus lent peut donc exclure les outils du premier tour. Les commandes ponctuelles de ce README (opik mcp configure, opik mcp status, --help, --check) incluent @latest ; elles n’exécutent donc jamais une copie mise en cache par uv depuis des mois.
Les variables d’environnement indiquent au serveur où se trouve votre instance Opik :
| Votre instance Opik | Variables d’environnement |
|---|---|
| Opik open source sur cette machine | OPIK_URL=http://localhost:5173/api |
| Opik open source sur un serveur | OPIK_URL=https://<host>/api, plus OPIK_API_KEY uniquement si le déploiement ajoute une authentification |
Plateforme Comet auto-hébergée (l’interface Opik se trouve à https://<host>/opik) | COMET_URL_OVERRIDE=https://<host>, OPIK_WORKSPACE, OPIK_API_KEY |
- L’édition open source expose son API à l’adresse
/apiet ne comporte qu’un seul espace de travail,default; elle n’a donc pas besoin deOPIK_WORKSPACE.COMET_URL_OVERRIDEdirigerait le serveur vers/opik/api, qui n’est pas exposé par l’édition open source. - Une instance Comet auto-hébergée comporte des espaces de travail nommés. Définissez
OPIK_WORKSPACEsur le segment qui suit/opik/dans votre URL Opik ; si cette variable est omise, les lectures proviennent de l’espace de travail par défaut de votre compte, sans aucun message d’erreur pour vous en avertir. - Une instance Comet auto-hébergée qui exécute le serveur OAuth MCP (désactivé par défaut) peut utiliser le flux hébergé à l’adresse
https://<host>/opik/api/v1/mcp. - Remplacez chaque valeur. Le serveur refuse les espaces de travail fictifs tels que
<your-workspace>ou${input:OPIK_WORKSPACE}; une URL fictive est envoyée telle quelle et la connexion échoue. OPIK_MCP_ANALYTICS_SOURCE=""dans le blocenvpermet à une installation auto-hébergée de ne pas afficher l’étiquette de source cloud-Comet dans les événements de télémétrie.
Avant d’ajouter le serveur à un client, vérifiez les paramètres : lancez-le avec le même environnement et --check. Il effectue un appel à Opik et affiche l’espace de travail ainsi que le nombre de projets détectés, ou indique les corrections à apporter avec un lien vers la documentation, puis se termine avec le code 0 ou 1. Un client ne peut pas vous le signaler avant une nouvelle session : Claude Code affiche « Connected » même si la clé est incorrecte, et Codex ne démarre rien avant ce moment.
OPIK_URL=http://localhost:5173/api uvx opik-mcp@latest --check
Enregistrez-le ensuite auprès de votre client : le serveur local, manuellement.
Installation avec un agent de programmation
Pour un agent IA à qui l’on demande d’installer le serveur, par exemple « install opik mcp ». L’objectif est d’enregistrer le serveur pour l’instance Opik de l’utilisateur, d’installer le pack de compétences Opik et de connecter l’utilisateur. Déterminez quelle instance Opik est utilisée sur cette machine et ne demandez à l’utilisateur que ce que vous ne pouvez pas savoir : une question par message, et attendez chaque réponse avant de poser la suivante. L’installateur de l’étape 3 effectue toute la configuration en une seule exécution ; réglez donc les étapes 1 et 2 avant de le lancer. uvx opik-mcp@latest --help affiche ces étapes.
-
Vérifiez ce qui est déjà configuré.
uvx opik@latest mcp statusCette commande affiche l’instance Opik enregistrée dans
~/.opik.config(URL et espace de travail, jamais la clé) ainsi que les clients qui ont déjà le serveur. Dans Claude Code, exécutez égalementclaude mcp list: cette commande affiche les connecteurs claude.ai et les entrées enregistrées sous d’autres noms. Elle affiche aussi la commande de chaque entrée ; celle d’une ancienne entrée npx peut contenir une clé API : ne la répétez pas.- Un serveur pour
https://www.comet.com/opik/api/v1/mcpsous n’importe quel nom, par exemple un connecteur claude.ai, signifie qu’il est déjà enregistré : n’en ajoutez pas un deuxième. Installez uniquement le pack de compétences avecnpx skills add comet-ml/opik-skills -g --all. Passez à l’étape 4 si le serveur affiche! Needs authentication. - L’installateur remplace sans demander une entrée
opik-mcpexistante, par exemple celle de l’ancien serveur npx. Demandez l’accord de l’utilisateur avant de le lancer.
- Un serveur pour
-
Identifiez l’instance Opik de l’utilisateur.
- Elle est enregistrée dans
~/.opik.config: utilisez-la et indiquez à l’utilisateur laquelle vous configurez. L’installateur la lit, clé API comprise ; ne demandez donc pas de clé. - Aucun
~/.opik.config:curl -s http://localhost:5173/api/is-alive/ping. Une réponse indique qu’il s’agit d’une instance Opik open source sur cette machine. Dans un shell en bac à sable, comme celui de Codex, l’absence de réponse peut signifier que le shell n’a pas accès au réseau, et non qu’aucune instance Opik n’est présente. - Aucun des deux : demandez à l’utilisateur et ne choisissez pas à sa place. Une URL Opik dans le projet, par exemple
OPIK_URL_OVERRIDEdans.env, permet de poser une question fermée. Sinon : « Quelle instance Opik utilisez-vous : Opik Cloud (www.comet.com), une instance Opik open source (son URL) ou une plateforme Comet auto-hébergée (son URL et son espace de travail) ? »
- Elle est enregistrée dans
-
Lancez l’installateur pour le client utilisé. Il installe le pack de compétences Opik avec le serveur, avec ou sans
--skills; conservez l’option dans toute commande que vous demanderez à l’utilisateur d’exécuter plus tard. Avec Opik Cloud, l’installateur ouvre la page de connexion dans le navigateur et attend une minute ; prévenez donc l’utilisateur avant de le lancer.uvx opik@latest mcp configure --ai-client claude-code --skills--ai-clientaccepte égalementcodex,cursor,vscodeetopencode. Pour une instance Opik enregistrée dans~/.opik.configou exécutée sur localhost, lancez la commande telle quelle :--deploymentmet de côté la configuration enregistrée, clé API comprise. Dans les autres cas, ajoutez l’option correspondant à l’instance indiquée par l’utilisateur à l’étape 2 :Instance Opik de l’utilisateur Option à ajouter Opik Cloud, www.comet.com--deployment cloudOpik open source --deployment local, et--url <url>si l’instance n’est pas sur localhostPlateforme Comet auto-hébergée, /opik/dans son URL--deployment self-hosted --url <url> --workspace <workspace>, avecOPIK_API_KEYdans le shellEn cas d’échec, par exemple si l’instance Opik ne répond pas, indiquez à l’utilisateur le message affiché et les éléments à vérifier, comme le VPN ou l’URL. Ne basculez pas vers une autre instance Opik.
-
Connexion à Opik Cloud. Si l’installateur indique que le serveur n’est pas encore connecté, demandez à l’utilisateur d’exécuter
claude mcp login opik-mcpou/mcpdans une session Claude Code, au lieu de l’exécuter vous-même : la commande attend l’ouverture du navigateur. Un connecteur claude.ai se connecte depuis/mcp. La connexion demande un espace de travail ; indiquez celui enregistré dans~/.opik.config, le cas échéant. -
Terminez. Indiquez ce qui a été installé et ce qu’il reste à faire. Nommez le pack de compétences : les compétences Opik, installées pour tous les projets, qui apprennent à l’agent à instrumenter, évaluer et déboguer avec Opik. Les clients chargent les serveurs MCP et les compétences au démarrage d’une session : demandez à l’utilisateur de démarrer une nouvelle session, puis de tester avec « liste mes projets Opik ».
Dans tous les cas :
- Ne demandez pas à l’utilisateur de coller une clé API dans le chat. Le serveur hébergé n’en a pas besoin ; sinon, récupérez-la depuis l’environnement du shell (
"$OPIK_API_KEY") ou laissez l’utilisateur exécuter la commande. - Ne devinez pas l’espace de travail. Il s’agit du segment qui suit
comet.com/opik/(ou/opik/sur une instance Comet auto-hébergée) dans l’URL Opik de l’utilisateur. - N’affichez pas
~/.claude.jsonni~/.opik.config: les deux peuvent contenir des clés API.uvx opik@latest mcp statusetclaude mcp listaffichent les informations nécessaires, et l’installateur lit lui-même la configuration. - Si une vérification des autorisations bloque une commande, ne cherchez pas à la contourner. Donnez à l’utilisateur la commande à exécuter (dans Claude Code,
!avant son exécution depuis l’invite).
Pour un client que l’installateur ne connaît pas, enregistrez-le manuellement avec les commandes de Configuration manuelle : le serveur hébergé pour Opik Cloud, le serveur local pour les autres.
- Avant d’enregistrer le serveur local, lancez-le avec l’environnement que vous allez lui transmettre et
--check, en exportantOPIK_API_KEYdans le shell plutôt qu’en l’écrivant dans la commande :OPIK_URL=http://localhost:5173/api uvx opik-mcp@latest --check. Il se termine avec le code 0 et indique l’espace de travail détecté, ou précise ce qu’il faut corriger. Une fois le serveur enregistré, Claude Code indique Connected même si la clé est incorrecte, et Codex n’effectue aucune vérification. - Claude Code refuse de remplacer une entrée
opik-mcpexistante : supprimez-la d’abord avecclaude mcp remove opik-mcp --scope user; la commandeaddde Codex la remplace. - Après l’enregistrement, dans Claude Code, consultez uniquement la ligne d’état :
claude mcp get opik-mcp | grep Status. La sortie complète affiche le blocenv, clé API comprise. Le serveur hébergé affiche! Needs authenticationjusqu’à l’exécution declaude mcp login opik-mcp. Codex ne dispose d’aucun mécanisme pour démarrer le serveur avant une session ;codex mcp get opik-mcpaffiche les paramètres enregistrés, avec les valeurs d’environnement masquées.
Configuration manuelle (sans vérification Opik ni pack de compétences)
La commande Démarrage rapide effectue toutes ces opérations pour Claude Code, Codex, Cursor, VS Code Copilot et opencode. Elle vérifie également quelle version d’Opik vous utilisez et installe le pack de compétences. N’effectuez l’enregistrement manuel que pour un autre client ou pour voir ce que l’installateur écrit. Un agent de programmation qui installe le produit pour un utilisateur exécute l’installateur : voir Installation avec un agent de programmation.
Serveur hébergé (Opik Cloud)
Claude Code, configuration manuelle
claude mcp add --scope user --transport http opik-mcp https://www.comet.com/opik/api/v1/mcp
Connectez-vous ensuite depuis /mcp → Authenticate dans une session Claude Code. Une fenêtre de navigateur s’ouvre ; la personne au clavier effectue cette étape. Depuis son propre terminal, claude mcp login opik-mcp fait la même chose. --scope user rend le serveur disponible dans tous les projets ; sans cette option, Claude Code ne l’enregistre que pour le répertoire courant. Par SSH, claude mcp login opik-mcp --no-browser affiche l’URL de connexion à ouvrir sur votre propre machine ; la dernière étape nécessite un terminal interactif (ssh -t).
Codex, configuration manuelle
codex mcp add opik-mcp --url https://www.comet.com/opik/api/v1/mcp
add ouvre la page de connexion ; codex mcp login opik-mcp l’ouvre à nouveau. Dans ~/.codex/config.toml, le même serveur se présente ainsi :
[mcp_servers.opik-mcp]
url = "https://www.comet.com/opik/api/v1/mcp"
Cursor, configuration manuelle
Utilisez le bouton sous le serveur hébergé ou ajoutez ceci à ~/.cursor/mcp.json :
{
"mcpServers": {
"opik-mcp": {
"url": "https://www.comet.com/opik/api/v1/mcp"
}
}
}
VS Code Copilot, configuration manuelle
Utilisez le bouton sous le serveur hébergé ou ajoutez ceci à .vscode/mcp.json dans votre espace de travail, ou à votre mcp.json utilisateur (MCP: Open User Configuration) :
{
"servers": {
"opik-mcp": {
"type": "http",
"url": "https://www.comet.com/opik/api/v1/mcp"
}
}
}
Autres clients
Tout client acceptant une URL peut utiliser le serveur hébergé :
npx add-mcp https://www.comet.com/opik/api/v1/mcp --name opik-mcp
Un client qui ne peut lancer que des commandes locales peut y accéder via npx -y mcp-remote https://www.comet.com/opik/api/v1/mcp.
Opik Cloud avec une clé API
Si personne ne peut effectuer la connexion dans le navigateur, par exemple lorsqu’un agent s’exécute sans surveillance depuis un script ou qu’un client ne prend pas en charge MCP OAuth, utilisez plutôt une clé API obtenue depuis comet.com/api/my/settings/, avec le serveur local configuré pour accéder à Opik Cloud :
claude mcp add --scope user opik-mcp \
--env OPIK_API_KEY="$OPIK_API_KEY" \
--env OPIK_WORKSPACE=<workspace> \
-- uvx opik-mcp
Les autres clients utilisent les mêmes deux variables dans leur bloc env. Définissez OPIK_WORKSPACE sur le segment qui suit comet.com/opik/ dans votre URL Opik
(https://www.comet.com/opik/acme-ai/projects → acme-ai). Si cette valeur est omise, le serveur envoie default, que Comet associe à l’espace de travail par défaut de votre compte. Les lectures peuvent donc provenir du mauvais espace de travail sans qu’aucune erreur ne soit signalée.
Serveur local (Opik auto-hébergé et open source)
Les exemples utilisent une version locale et open source d’Opik. Pour une instance Comet auto-hébergée, remplacez les trois variables par celles du tableau. Après avoir ajouté le serveur, démarrez une nouvelle session et demandez : « liste mes projets Opik ».
Claude Code, configuration manuelle
claude mcp add --scope user opik-mcp --env OPIK_URL=http://localhost:5173/api -- uvx opik-mcp
Pour une instance Comet auto-hébergée, avec la clé dans la variable OPIK_API_KEY de votre shell :
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
Vous pouvez aussi modifier directement ~/.claude.json :
{
"mcpServers": {
"opik-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["opik-mcp"],
"env": {
"OPIK_URL": "http://localhost:5173/api"
}
}
}
}
claude mcp get opik-mcp affiche ✔ Connected une fois le serveur démarré. Cela ne prouve pas que l’URL ou la clé sont correctes, car seul un appel d’outil contacte Opik ; c’est le cas de --check (le serveur local). Cette commande affiche également le bloc env, clé API comprise.
Codex, configuration manuelle
codex mcp add opik-mcp --env OPIK_URL=http://localhost:5173/api -- uvx opik-mcp
Vous pouvez aussi modifier ~/.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 ne transmet à un serveur local que les variables de env et les noms de env_vars. Une clé exportée dans votre shell ne lui est donc pas transmise autrement.
Cursor, configuration manuelle
Ajoutez ceci à ~/.cursor/mcp.json (global) ou à .cursor/mcp.json (projet), ou utilisez Cmd+Shift+J → Features → Model Context Protocol :
{
"mcpServers": {
"opik-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["opik-mcp"],
"env": {
"OPIK_URL": "http://localhost:5173/api"
}
}
}
}
Délai d’expiration de 60 s dans Cursor. Cursor impose un délai maximal strict aux appels d’outils, qui n’est pas réinitialisé par les notifications de progression. Voir Limites connues des hôtes.
VS Code Copilot, configuration manuelle
Ajoutez ceci à .vscode/mcp.json dans votre espace de travail, ou à votre mcp.json utilisateur (MCP: Open User Configuration) :
{
"servers": {
"opik-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["opik-mcp"],
"env": {
"OPIK_URL": "http://localhost:5173/api"
}
}
}
}
MCP Inspector (tests manuels)
OPIK_URL=http://localhost:5173/api npx @modelcontextprotocol/inspector uvx opik-mcp
Vous venez de npx opik-mcp ?
Le serveur TypeScript (npm opik-mcp@2) est obsolète et cessera de traiter les requêtes le 2026-11-15. Pour une nouvelle installation, exécutez la commande Démarrage rapide ; uvx opik-mcp est la commande qu’un client exécute pour démarrer le serveur, et non un installateur. Pour migrer une configuration existante sur Opik Cloud, passez au serveur hébergé et supprimez la clé API. Sinon, dans la configuration de votre client MCP, remplacez npx -y opik-mcp par uvx opik-mcp. Certaines variables d’environnement ont été renommées et les options de ligne de commande ne sont plus lues : consultez le https://github.com/comet-ml/opik-mcp/blob/main/legacy/typescript/MIGRATION.md.
Politique d’assistance : DEPRECATED.md.
Le code source TypeScript est disponible sous le tag Git legacy-typescript-final.
Outils
opik-mcp expose une interface réduite, axée sur les résultats, qui couvre l’ensemble du cycle de vie (lire → annoter → organiser → créer → itérer).
| Outil | Fonction |
|---|---|
read | Lecture universelle par identifiant / nom / URI opik:// |
list | Liste universelle avec filtre de nom facultatif et pagination |
write | Écriture universelle — journaliser des traces/spans, attribuer des scores, ajouter des commentaires, enregistrer des prompts, gérer des jeux de données et des expériences |
schema | Examiner les schémas des opérations d’écriture (utilisés par le LLM pour construire des charges utiles valides) |
read_skill | Lire l’une des compétences d’agent Opik fournies avec ce serveur |
read
Un seul outil pour toute question du type « affiche-moi X ». Il prend un entity_type et un id
(UUID ou, pour les types nommables, nom), ou un URI opik:// complet. Les lectures composites (trace, prompt, thread, agent_insights_issue) intègrent leurs éléments enfants afin qu’un seul appel fournisse une vue complète.
L’enregistrement que vous nommez est renvoyé dans son intégralité. Ce n’est pas le cas des éléments enfants intégrés : leur contenu est récupéré avec truncate=true du backend. Un champ de plus d’environ 10 Ko est tronqué dans ClickHouse et les images base64 sont remplacées par "[image]" — sans cela, une pièce jointe répétée dans 200 spans coûterait plus que tout le reste de la lecture. La réponse le signale dans spanBodies / messageBodies, et chaque élément enfant peut être récupéré dans son intégralité avec son propre read("span", id) ou read("trace", trace_id), qui appellent des points de terminaison ne comportant aucun paramètre truncate.
La longueur des collections intégrées est également limitée : 200 spans, 200 tours, 100 versions de prompt. Au-delà, spansTruncated / messagesTruncated / versionsTruncated vaut true, et une ligne moreSpans / moreMessages / moreVersions adjacente indique le nombre d’éléments ainsi que l’appel list(...) exact permettant de poursuivre à partir de l’endroit où s’arrête la partie intégrée.
Entités prises en charge : project, trace, span, dataset, dataset_item,
experiment, prompt, thread, agent_insights_issue. La recherche par nom est disponible pour project, experiment, prompt, dataset (plus lente — deux appels API — et susceptible de renvoyer plusieurs résultats). thread et agent_insights_issue sont associés à un projet : transmettez project_id ou project_name, ou un lien/URI contenant le projet. dataset et dataset_item s’appelaient auparavant test_suite et test_suite_item ; les anciens noms fonctionnent toujours, mais ne sont plus proposés. Le nouveau code doit utiliser les nouveaux noms.
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>",
)
Un lien copié depuis l’interface Opik fonctionne comme id : un lien vers un fil ou une page Diagnostics contient le projet. Aucun project_id n’est donc nécessaire, et le type d’entité est déduit du lien.
Une lecture project répond en un seul appel à la question « comment se porte mon projet ? ». Elle renvoie {project, summary, vocabulary, contains, url} : l’enregistrement, puis les quatre indicateurs affichés sous forme de cartes sur la page Logs (nombre de traces, taux d’erreur, durée moyenne, coût total) pour les 7 derniers jours, comparés aux 7 jours précédents, uniquement pour le trafic du SDK, comme à l’écran. since / until permettent de déplacer cette période ; since="30d" correspond à la période affichée par défaut dans l’interface. Un taux ou une moyenne calculé sur une période sans traces est renvoyé sous la forme null, car un taux d’erreur de 0 % pendant une semaine sans trafic ne signifie pas que tout va bien.
vocabulary est la carte dont vous avez besoin avant de poser toute autre question : les noms des scores de feedback du projet, ses clés d’utilisation des jetons et les règles d’automatisation qui attribuent des scores à ses traces. Ce sont les noms à utiliser dans un filtre ou dans series= ci-dessous. Si vous les devinez, vous obtiendrez une page vide qui semble annoncer une bonne nouvelle. Le nombre de scores et de règles est limité ; le total réel est toujours indiqué, ainsi que l’appel permettant de récupérer le reste. Toutes les clés d’utilisation sont répertoriées, car rien d’autre ne permet de les énumérer. contains indique l’expérience, le jeu de données, la version de prompt et l’exécution d’optimisation les plus récents, afin de répondre à la question « que s’est-il passé ici ? » sans quatre appels supplémentaires. Si une partie n’a pas pu être chargée, cela est signalé au lieu de la laisser vide ; les parties vides sont omises.
Une lecture agent_insights_issue renvoie {issue, example_trace_ids, details} :
l’enregistrement du problème Diagnostics (nom, description, cause, correctif suggéré, gravité, état), les identifiants dédupliqués des traces qui le présentent (le même échantillon que sur la page Diagnostics — ouvrez-en une avec read("trace", id)) et la répartition par jour. Le contenu des traces n’est pas intégré, ce qui permet de limiter la lecture à un seul appel backend. since / until restreignent les lignes par jour ; par défaut, la période est illimitée. Lorsque le serveur connaît l’URL Opik et l’espace de travail de la session, la lecture inclut également url (la page Diagnostics du problème) et trace_url_template (un lien direct vers n’importe laquelle des traces d’exemple), afin que l’assistant puisse vous fournir un lien cliquable. Dans une session OAuth dont l’espace de travail n’a pas pu être déterminé, les liens sont omis plutôt que devinés.
Les traces ne contiennent pas d’URL : il est impossible de déduire leur lien à partir des champs renvoyés par read ou list, et une URL devinée renvoie une erreur 404. Les instructions de session indiquent plutôt un modèle, .../v1/session/redirect/projects/?trace_id={trace_id}&path=..., que l’assistant complète avec un identifiant pour vous fournir un lien. Celui-ci passe par la redirection d’opik-backend, qui détermine le projet et l’espace de travail à partir de la trace. Il fonctionne donc même lorsqu’une URL directe vers le projet ne le peut pas, y compris dans une session OAuth dont l’espace de travail n’a pas été déterminé. C’est le même lien que celui affiché par le SDK Python pour une trace.
list
Parcourir ou rechercher une collection avec pagination. Les types associés à un projet (trace,
span, thread, agent_insights_issue, dataset_item, prompt_version)
nécessitent leur parent : un UUID ou un nom de projet, un UUID de jeu de données ou un UUID de prompt.
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"')
Filtres. trace, span, thread, experiment et dataset_item acceptent une chaîne OQL, selon la même grammaire que search_traces(filter_string=…) du SDK :
<field>[.<key>] <op> <value> [AND ...]
ops: = != > >= < <= contains not_contains starts_with ends_with is_empty is_not_empty in not_in
Les chaînes de caractères sont entre guillemets doubles, les nombres sont sans guillemets, duration est exprimé en millisecondes,
les dates sont des instants ISO-8601 avec un fuseau horaire ("2026-09-08T10:00:00Z").
Les scores et les dictionnaires prennent une clé : feedback_scores.accuracy < 0.5,
metadata.environment = "prod". AND est le seul connecteur.
Comme sur la page Logs de l’interface, les listes de traces, de spans et de threads ajoutent source = "sdk" afin que les traces des évaluateurs, du playground et des expériences ne gênent pas ; indiquez vous-même le nom source pour les voir. La première ligne de sortie reprend le filtre appliqué.
Un filtre incorrect échoue avant d’atteindre le backend et indique ce qu’il faut pour le corriger :
la position d’une erreur de syntaxe, le nom de champ le plus proche, les opérateurs valides pour
le type du champ ou le format de valeur attendu. Les champs dont les valeurs appartiennent à un ensemble fermé
(source, span type, thread status, visibility_mode) sont également vérifiés,
y compris chaque élément d’une liste in. source est le seul champ
validé par le backend lui-même, qui répond par une erreur 500 plutôt que 400 en cas de valeur inconnue ; source = "SDK" provoquerait donc une erreur serveur opaque pour une lettre majuscule. Les autres sont comparés comme des chaînes et renvoient une page vide,
ce qui signifie « aucune correspondance » alors que le sens est « valeur inexistante ». Demandez
schema("list.trace") (ou list.span, list.thread, list.experiment) pour
consulter la référence complète des champs, y compris les valeurs acceptées.
Trouver un cas dans un jeu de données. list(entity_type="dataset_item", dataset_id=…) filters on the case itself: data.<key> pour les clés avec lesquelles le
jeu de données a été créé, full_data pour rechercher une sous-chaîne dans l’ensemble de la charge utile (analyse complète — indiquez une clé si possible), ainsi que id, tags, source, trace_id,
span_id et les horodatages. data.<key> n’accepte que les six opérateurs de chaîne
(=, !=, contains, not_contains, starts_with, ends_with) ; le
backend répond par une erreur 400 à une comparaison, ce filtre est donc refusé avant l’appel.
Le point de terminaison ne propose ni tri ni recherche en texte libre — sort est refusé
plutôt qu’ignoré. read(entity_type="dataset_item", id=…) renvoie un cas complet,
ce qui permet de récupérer une valeur tronquée dans le tableau.
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
Avec experiment_ids, la même liste porte plutôt sur la comparaison — les cas avec
chaque exécution associée — et filtre les exécutions (feedback_scores.<name>,
output, duration). Il s’agit de deux ensembles de champs différents sur deux points de terminaison backend :
schema("list.dataset_item_case") correspond aux cas propres au jeu de données,
schema("list.dataset_item") à la comparaison.
Tri. trace, span, thread et experiment acceptent
sort="<field> [asc|desc]", desc par défaut et un seul champ :
sort="duration desc", sort="total_estimated_cost",
sort="feedback_scores.accuracy asc", sort="usage.total_tokens". Le champ est
vérifié par rapport à la liste des champs triables de l’entité avant l’appel, car le backend
ignore silencieusement les champs qu’il ne peut pas trier. Dans les espaces de travail très volumineux, le backend supprime complètement le tri ; l’en-tête le signale dans ce cas.
dataset_item ne permet le tri que dans une comparaison (avec experiment_ids) : le point de terminaison des éléments n’accepte aucun paramètre de tri, un tri sur une liste simple est donc refusé plutôt qu’ignoré.
Période et recherche. trace, span et thread acceptent since et
until, chacun étant une durée relative ("30m", "1h", "7d") ou un instant ISO-8601
avec un fuseau horaire ; il n’est donc pas nécessaire de calculer l’heure pour « la dernière heure ». La période est définie par l’heure de création de l’enregistrement, ce qui est peu coûteux pour le backend et correspond à start_time à quelques secondes près pour le trafic en direct. Pour une limite exacte, placez
start_time dans filters. Les trois mêmes types acceptent search, du texte libre recherché
n’importe où dans l’identifiant, le nom, l’entrée, la sortie, les métadonnées, les tags et l’identifiant du thread. La recherche parcourt l’ensemble du projet sur le backend ; le premier appel sur un grand projet peut donc prendre plusieurs dizaines de secondes. Ces appels ont un délai d’expiration de 60 secondes. L’ajout de since les accélère à nouveau.
Lecture du tableau. Les durées sont étiquetées duration_ms / ttft_ms et
affichées en millisecondes entières ; le champ reste duration dans filters et
sort. Les horodatages sont affichés à la seconde et les coûts sous forme de nombres décimaux simples.
Les lignes de projet contiennent last_updated_trace_at pour voir quel projet reçoit du trafic en direct ; les lignes de thread contiennent le premier message. Une page vide avec une période indique quand la dernière trace du projet a été enregistrée ; une page vide avec le filtre par défaut source = "sdk" explique comment afficher les autres sources. Un nom project_name mal orthographié renvoie le nom existant le plus proche.
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")
Problèmes de diagnostic. agent_insights_issue correspond à la page Diagnostics via
MCP : les échecs récurrents regroupés par la tâche Diagnostics d’Opik pour un projet,
classés comme dans l’interface (du plus récemment observé au moins récemment observé). Les colonnes sont severity,
status, total_occurrences (somme sur toute la période), latest_count (le jour du rapport le plus récent, la date à laquelle se réfère la description du problème) et last_seen.
Les problèmes ouverts sont affichés par défaut ; passez status="resolved" ou "closed" pour afficher les autres. read et list répondent également à issue, le nom utilisé par l’interface pour les désigner ; le nom long est celui de l’énumération entity_type, afin que cette entité n’y apparaisse pas deux fois. Les nombres sont calculés sur toute la période pour correspondre à l’interface ; les mêmes since / until
que pour les traces permettent de limiter la période, tronquée aux jours de rapport UTC, car Diagnostics agrège les données par jour.
Une liste vide en indique la raison, car « rien ne fonctionne mal » et « personne n’a activé Diagnostics » auraient sinon le même sens. Il existe cinq états : Diagnostics n’est pas disponible sur ce déploiement, n’est pas activé pour ce projet, est désactivé, est activé mais n’a pas été exécuté récemment, ou est activé et n’a détecté aucun problème, avec l’heure de la dernière analyse. Les états sur lesquels vous pouvez agir indiquent l’appel à effectuer, et chaque état renvoie à la page Diagnostics du projet.
Une liste non vide indique sa période. Les problèmes correspondent aux éléments regroupés lors de la dernière analyse,
la réponse se termine donc par Report covers data through <time> ; si la période demandée dépasse cette date,
elle indique la partie non couverte et comment la couvrir : un déclencheur lorsque la nouvelle analyse remonte assez loin, sinon les traces brutes avec le since fourni. Si vous demandez une semaine pour un projet analysé chaque nuit, le dernier jour manque dans les résultats regroupés ; c’est ce qui l’indique.
write("agent_insights_job.enable", {"project_name": "demo"}) active Diagnostics.
Les analyses sont ensuite quotidiennes, et il est sans risque de répéter l’appel.
write("agent_insights_job.trigger", …) lance immédiatement une analyse des dernières 24 heures, sans
attendre l’exécution nocturne. Les deux nécessitent la même autorisation que la lecture des problèmes, et les deux sont refusés si Diagnostics n’est pas disponible sur le déploiement.
Un problème évolue au cours de son cycle de vie avec
write("agent_insights_issue.resolve", {"issue_id": "<uuid>", "project_name": "demo"})
— traité — ou …close s’il ne mérite pas d’intervention, et …reopen pour le remettre dans la liste des problèmes ouverts. Les trois nécessitent la même autorisation et renvoient un lien vers la vue où le problème a été déplacé, car un problème résolu n’apparaît plus sur la page par défaut. Déterminer si un échec est corrigé relève du jugement ; ces actions sont donc à effectuer sur demande : l’assistant n’a pas à faire le ménage dans la liste pendant le triage.
Métriques au fil du temps. project_metric représente une métrique pour un projet sous forme de tableau de périodes : nombres de traces, de spans et de threads, durées, taux d’erreur,
coûts, utilisation des jetons et scores de feedback. Elle répond à la question qui suit la vue d’ensemble : quand quelque chose a changé.
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
Les lignes correspondent à des périodes, pas à des enregistrements ; page, size et sort sont donc refusés
plutôt qu’ignorés. interval est hourly, daily, weekly ou total ;
si cette valeur est omise, elle suit la période comme l’onglet Metrics : par heure jusqu’à 3
jours, par jour jusqu’à 30 jours, par semaine au-delà. Un graphique par défaut comporte donc quelques dizaines de lignes, quelle que soit la période ; un mois par heure (721 lignes) est une demande explicite.
since / until acceptent les mêmes formats que partout ailleurs et utilisent par défaut les 7 derniers jours. filters utilise les champs de l’entité concernée par la métrique ; une métrique de span est donc filtrée par les champs de span.
breakdown répartit chaque période selon tags, name, error_info, error_type,
model, provider, span_type, guardrail_name ou metadata.<key>. Toutes les métriques n’acceptent pas toutes ces options, et sept n’en acceptent aucune ; l’outil sait lesquelles et l’indique avant d’appeler le backend, en nommant une métrique qui répond à la même question lorsqu’il en existe une. Trois familles renvoient plusieurs séries à la fois (une durée sous forme de p50/p90/p99, un score par nom, l’utilisation des jetons par clé) ; lors d’un regroupement, le backend n’en représente qu’une à la fois, et series= permet de la choisir : un percentile, un nom de score ou une clé d’utilisation. La durée utilise par défaut p50 et l’utilisation des jetons total_tokens ; la valeur utilisée est reprise sur la première ligne.
Les périodes vides sont omises et comptabilisées en dessous ; un mois calme ne produit donc que quelques lignes au lieu d’une colonne de zéros, et un taux pour une période sans traces est absent plutôt que présenté comme nul.
Demandez schema("list.project_metric") pour consulter le tableau des métriques, les intervalles et la matrice de regroupement par métrique.
Les noms d’un projet. score_name répertorie les noms de scores de feedback enregistrés dans un projet et online_rule les évaluateurs de règles d’automatisation qui y sont configurés ; c’est de là que proviennent la plupart de ces noms. Les deux renvoient les mêmes listes que read("project", …), au complet et avec pagination, lorsque la version limitée de la vue d’ensemble ne suffit pas.
list(entity_type="score_name", project_name="demo")
list(entity_type="online_rule", project_name="demo")
write
Dispatcheur universel d’écriture. Passez operation + data ; le dispatcheur
valide la charge utile, applique le verbe REST approprié et renvoie la réponse du backend.
Opérations :
| Opération | Fonction |
|---|---|
trace.create | Enregistrer une trace unique (ou un lot). Parent des spans / scores / commentaires. |
trace.update | Finaliser ou modifier une trace existante. |
span.create | Enregistrer un span sur une trace existante (ou un lot). |
score.create | Associer un score de feedback numérique à une trace, un span ou un thread. |
comment.create | Associer un commentaire en texte libre à une trace, un span ou un thread. |
prompt_version.save | Enregistrer une nouvelle version de prompt (crée le prompt par nom s’il n’existe pas). |
dataset.create | Créer un jeu de données — type: "test_suite" en fait une suite de tests d’évaluation. |
dataset_item.upsert | Insérer ou mettre à jour des éléments dans un jeu de données (toujours au format enveloppe). |
experiment.create | Créer une expérience associée à un jeu de données. |
experiment_item.create | Associer des lignes trace + dataset_item à une expérience. |
thread.close | Fermer un thread (le marquer comme inactif). Passez thread_id et le projet. |
thread.open | Rouvrir un thread fermé. Passez thread_id et le projet. |
agent_insights_job.enable | Activer Diagnostics pour un projet (analyses quotidiennes, appel répétable sans risque). |
agent_insights_job.trigger | Lancer immédiatement une analyse Diagnostics sur les dernières 24 heures. |
agent_insights_issue.resolve | Marquer un problème Diagnostics comme traité (demander d’abord à l’utilisateur). |
agent_insights_issue.close | Marquer un problème Diagnostics comme ne méritant pas d’intervention (demander d’abord à l’utilisateur). |
agent_insights_issue.reopen | Remettre un problème Diagnostics résolu ou fermé dans la liste des problèmes ouverts. |
annotation_queue.create | Créer une file d’annotation pour un projet, éventuellement avec une vue d’annotateur personnalisée. |
annotation_queue.update | Modifier une file d’annotation ; définir, remplacer ou effacer sa vue d’annotateur. |
write(
operation="score.create",
data={
"target": "trace",
"target_id": "7f2e3c8a-…",
"name": "helpfulness",
"value": 0.9,
"reason": "great recovery",
},
)
schema
Examinez la structure JSON exacte et les champs obligatoires de toute opération d’écriture avant
de l’appeler — utile si vous ne savez pas à quoi data doit ressembler. Renvoie
le schéma, le scope OAuth et un exemple validé. Simple consultation, sans appel au backend.
schema(operation="score.create")
schema(operation="prompt_version.save")
Le même outil répond à list.trace, list.span, list.thread et
list.experiment avec la référence de l’outil list pour cette entité : chaque
champ filtrable avec son type et ses opérateurs valides, les champs triables, si
une fenêtre temporelle et une recherche en texte libre s’appliquent, ainsi que deux filtres d’exemple.
schema(operation="list.trace")
Configuration
Ces paramètres configurent le serveur local ; chacun est une variable d’environnement. Le serveur hébergé sur Opik Cloud n’en utilise aucun.
Identité / point de terminaison
| Variable | Valeur par défaut | Notes |
|---|---|---|
OPIK_API_KEY | — | Clé API, pour un Comet auto-hébergé ou pour Opik Cloud sans le serveur hébergé. Opik open source n’en a pas besoin, sauf si le déploiement ajoute une authentification. |
OPIK_WORKSPACE | unset | Nom de l’espace de travail. Sur le cloud avec une clé API, si cette variable n’est pas définie, default est envoyé et correspond à l’espace de travail par défaut de votre compte — définissez-la explicitement si vous travaillez dans un autre espace, sinon les lectures proviendront silencieusement du mauvais espace de travail. Ne la définissez pas avec OAuth (le jeton contient cette information) ni sur une installation locale/OSS (default est le seul espace de travail disponible). |
COMET_WORKSPACE | — | Alias obsolète de OPIK_WORKSPACE (compatibilité ascendante). OPIK_WORKSPACE est prioritaire si les deux sont définis. |
COMET_WORKSPACE_ID | unset | UUID facultatif de l’espace de travail. Ajouté aux événements analytiques lorsqu’il est défini, et prioritaire sur l’UUID résolu. Rarement nécessaire — les installations OAuth obtiennent automatiquement l’UUID depuis le jeton. |
COMET_URL_OVERRIDE | https://www.comet.com | Définissez cette variable sur l’hôte de votre Comet auto-hébergé, ou sur https://dev.comet.com pour l’environnement de préproduction. |
OPIK_URL | dérivé de COMET_URL_OVERRIDE + /opik/api | Définissez cette variable pour Opik open source, qui expose son API à /api (http://localhost:5173/api en local). Sur une plateforme Comet, ne la remplacez que si Opik se trouve sur un hôte ou un chemin différent de l’interface Comet. |
OPIK_DEFAULT_PROJECT_NAME | unset | Lorsqu’elle est définie, le bloc instructions propre à la session indique au LLM de transmettre cette valeur comme project_name à chaque appel d’outil, sauf si l’utilisateur nomme un autre projet. |
Serveur / transport
| Variable | Valeur par défaut | Notes |
|---|---|---|
OPIK_MCP_TRANSPORT | stdio | stdio pour un lancement par l’hôte, streamable-http pour écouter sur un port. |
OPIK_MCP_HOST | 127.0.0.1 | Hôte de liaison uvicorn (streamable-http uniquement). |
OPIK_MCP_PORT | 8080 | Port de liaison uvicorn (streamable-http uniquement). |
OPIK_MCP_RELOAD | false | true pour activer --reload de uvicorn (développement uniquement). |
OPIK_MCP_AS_URL | unset | URL du serveur d’autorisation OAuth, annoncée dans /.well-known/oauth-protected-resource (RFC 9728) et utilisée comme cible proxy pour les requêtes de découverte AS. Nécessaire pour que les hôtes MCP puissent initialiser le flux OAuth sur HTTP. |
OPIK_MCP_RESOURCE_URI | unset | URI publique canonique de ce serveur, annoncée comme resource dans les métadonnées de la ressource protégée et utilisée pour dériver l’indication WWW-Authenticate. |
OPIK_MCP_OAUTH_VALIDATION_CACHE_TTL_S | 30 | Durée pendant laquelle une réponse « valide » de l’introspection de jeton d’opik-backend est considérée comme fiable avant que la requête suivante utilisant le même jeton OAuth ne relance l’introspection. Limite la charge ajoutée au backend par la validation de chaque requête et la période pendant laquelle un jeton expiré est encore transmis (cette période prend également fin dès que le backend renvoie un premier 401). La durée est plafonnée par le expires_at propre au jeton, si le backend en indique un. |
OPIK_MCP_LOG_LEVEL | INFO | Seuil du journal stderr. |
Choisir un transport
Deux formats de jeton Bearer, deux contrats de transport HTTP. Un jeton d’accès OAuth opik_mcp_at_… est validé à chaque requête auprès du point de terminaison d’introspection de jeton d’opik-backend (avec mise en cache, voir OPIK_MCP_OAUTH_VALIDATION_CACHE_TTL_S) ;
un jeton expiré ou révoqué reçoit une réponse HTTP 401 avec
WWW-Authenticate: Bearer error="invalid_token", sur laquelle les hôtes MCP s’appuient pour déclencher leur
flux silencieux de renouvellement refresh_token. Une clé API Opik n’est pas validée localement : elle est transmise telle quelle à opik-backend, qui est son unique point de contrôle. Choisissez le transport en fonction du déploiement :
| Scénario | Transport |
|---|---|
| Opik Cloud | Rien à exécuter : le serveur hébergé est ce serveur sur HTTP, exécuté par Comet |
| Client MCP et Opik sur la même machine (installation OSS locale) | stdio (recommandé — le plus simple, sans port ni configuration OAuth) |
| Client MCP local → Opik auto-hébergé | stdio avec les variables d’environnement du déploiement, ou HTTP avec OAuth (OPIK_MCP_AS_URL pointant vers le backend) |
| opik-mcp servi derrière le même point d’accès qu’opik-backend | HTTP — les jetons Bearer sont validés par le backend à chaque requête |
Remarque pour les installations OSS locales : le backend OSS n’authentifie pas les requêtes ; un opik-mcp en HTTP placé devant lui est donc aussi ouvert que l’API REST OSS elle-même.
Conservez la liaison par défaut 127.0.0.1 (et privilégiez stdio) sur les réseaux partagés.
Télémétrie
| Variable | Valeur par défaut | Notes |
|---|---|---|
OPIK_MCP_ANALYTICS_ENABLED | true | Définissez cette variable sur false pour désactiver toute télémétrie autre que Sentry. |
| `OPIK_MCP_SENTRY_ENABLED | true | Set to false pour désactiver toute télémétrie Sentry. |
| ======= |
Limites connues des hôtes
Les hôtes diffèrent par la durée pendant laquelle ils autorisent l’exécution d’un appel d’outil :
- Claude Code — aucun délai d’expiration documenté pour les appels d’outil. Recommandé.
- Cursor — délai d’expiration strict de 60 s qui ne se réinitialise pas en cas de progression (bogue en amont).
- MCP Inspector —
MAX_TOTAL_TIMEOUTlimite la durée totale (60 s par défaut). Augmentez cette valeur dans l’interface d’Inspector pour les opérations longues.
Si un appel reste bloqué, définissez OPIK_MCP_LOG_LEVEL=DEBUG pour obtenir le journal complet de la requête.
Dépannage
La configuration fonctionne-t-elle ? Lancez le serveur avec l’environnement de sa configuration client et
--check : OPIK_URL=http://localhost:5173/api uvx opik-mcp@latest --check. Il
indique le nom de l’espace de travail et les projets qu’il détecte, ou précise les corrections à apporter. Les erreurs du serveur indiquent également les modifications à effectuer et renvoient vers la page de documentation correspondante.
OPIK_API_KEY n’est pas pris en compte — la variable n’est pas transmise au processus du serveur. Dans Claude Code / Cursor / VS Code, les variables d’environnement ne s’appliquent que si elles se trouvent dans le bloc env de la configuration du serveur MCP, et non dans votre shell ; Codex transmet également les noms répertoriés dans env_vars. Démarrez une nouvelle session après modification, car les clients lisent la configuration au démarrage d’une session.
Les requêtes sont envoyées à /opik/api sur une installation Opik open source — COMET_URL_OVERRIDE est destiné à une plateforme Comet auto-hébergée. La version open source expose son API à /api : définissez plutôt OPIK_URL=http://localhost:5173/api (ou https://<host>/api). Au démarrage, le serveur émet un avertissement si l’hôte est cette machine, et --check répond « No Opik API at … ».
L’appel Cursor expire au bout de 60 s — il s’agit d’un bogue connu de Cursor, pas de opik-mcp. Réduisez la portée de l’appel (un size plus petit, une fenêtre plus étroite) ou exécutez la même opération dans Claude Code, qui n’a pas de limite stricte.
Serveur absent, ouverture de session impossible, mauvais espace de travail, uvx introuvable.
Ces problèmes sont traités dans la section de dépannage de la documentation.
uvx opik@latest mcp status répertorie chaque client pour lequel le serveur est configuré et indique si sa configuration a divergé.
Développement
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
Cibles courantes :
| Cible | Fonction |
|---|---|
make install | uv sync --locked --extra dev |
make run | Exécuter le serveur MCP (stdio par défaut). |
make run-dev | Exécuter avec la journalisation DEBUG et --reload de uvicorn. |
make dev | Exécuter via mcp dev (wrapper de mode développement d’Inspector). |
make inspect | Lancer MCP Inspector sur un serveur en cours d’exécution. |
make test | uv run pytest -q. |
make lint | ruff check + vérification du formatage. |
make format | ruff format + ruff check --fix. |
make typecheck | mypy. |
make check | lint + typecheck + test. |
Structure du dépôt :
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
Obtenir de l’aide
- Ouvrir un ticket pour signaler des bogues ou demander des fonctionnalités
- Documentation Opik pour la documentation du SDK et du backend
- Slack de la communauté Comet pour poser des questions
Licence
Apache-2.0.