Surveillance des serveurs MCP (Monitoring Model Context Protocol)

Le Model Context Protocol (MCP) est une norme qui permet aux assistants IA tels que Claude Desktop et Copilot d' GitHub de se connecter en toute sécurité à des sources de données et à des outils externes. Surveillez les interactions entre votre serveur MCP et vos clients à l'aide d' Instana, afin d'obtenir une vue d'ensemble de l'exécution des outils, des flux de requêtes et des performances.

Avant de commencer

Assurez-vous que les conditions préalables suivantes sont remplies.

  • Python 3.8 ou une version ultérieure
  • Une implémentation du serveur MCP
  • Instana est configuré pour votre application, consultez la section « Pour commencer »

A propos de cette tâche

Instana s'intègre à OpenLLMetry pour offrir un traçage distribué aux applications MCP, en générant automatiquement des segments pour les opérations clés, notamment l'exécution des outils, le traitement des requêtes et les interactions client-serveur.

Procédure

Pour configurer les serveurs MCP, procédez comme suit.
  1. Installez l' OpenLLMetry e dans votre environnement de serveurs MCP.
    # Using pip
    pip install traceloop-sdk
    
    # Using uv
    uv add traceloop-sdk
  2. Ajoutez l'initialisation d' OpenLLMetry s au code de votre serveur MCP.
    import os
    import sys
    
    # Disable default OTel exporters
    os.environ.setdefault("OTEL_TRACES_EXPORTER", "none")
    os.environ.setdefault("OTEL_METRICS_EXPORTER", "none")
    os.environ.setdefault("OTEL_LOGS_EXPORTER", "none")
    
    try:
        from traceloop.sdk import Traceloop
        from traceloop.sdk.decorators import workflow
    except ImportError:
        Traceloop = None
        print("OpenLLMetry not installed. Install with: pip install traceloop-sdk", file=sys.stderr)
    
    # Initialize OpenLLMetry
    if Traceloop is not None:
        try:
            Traceloop.init(app_name="your-mcp-server-name", disable_batch=True)
        except Exception as e:
            print(f"OpenLLMetry initialization warning: {e}", file=sys.stderr)
  3. Personnalisez la page d'accueil de votre serveur.

    Utilisez le @workflow décorateur sur la fonction principale de votre serveur pour créer un span racine couvrant tout le cycle de vie du serveur :

    @workflow(name="mcp_server_workflow")
    def start_server():
        """Start MCP server."""
        # Your server initialization code
        mcp.run(transport="stdio")  # or "streamable-http"
    
    if __name__ == "__main__":
        start_server()

Serveur MCP « Météo »

L'exemple suivant présente un serveur MCP sur lequel la fonctionnalité d'observabilité est activée :

from __future__ import annotations

import os
import sys
from typing import Any, Dict, Optional

# Configure OTel exporters
os.environ.setdefault("OTEL_TRACES_EXPORTER", "none")
os.environ.setdefault("OTEL_METRICS_EXPORTER", "none")
os.environ.setdefault("OTEL_LOGS_EXPORTER", "none")

try:
    from traceloop.sdk import Traceloop
    from traceloop.sdk.decorators import workflow
except ImportError:
    Traceloop = None

import httpx
from mcp.server.fastmcp import FastMCP

# Initialize OpenLLMetry
if Traceloop is not None:
    try:
        Traceloop.init(app_name="Weather-MCP-Server", disable_batch=True)
    except Exception as e:
        print(f"OpenLLMetry initialization warning: {e}", file=sys.stderr)

mcp = FastMCP(name="Weather")
NWS_API_BASE = "https://api.weather.gov"
NWS_USER_AGENT = "Weather-MCP-Server (dev@example.com)"

async def make_nws_request(url: str) -> Optional[Dict[str, Any]]:
    """Make a GET request to NWS API."""
    headers = {
        "User-Agent": NWS_USER_AGENT,
        "Accept": "application/geo+json",
    }
    async with httpx.AsyncClient(timeout=30.0) as client:
        try:
            resp = await client.get(url, headers=headers)
            resp.raise_for_status()
            return resp.json()
        except Exception as e:
            print(f"NWS request failed: {e}", file=sys.stderr)
            return None

@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """Get weather forecast for a location.

    Args:
        latitude: Latitude coordinate
        longitude: Longitude coordinate

    Returns:
        Weather forecast as formatted string
    """
    try:
        lat, lon = float(latitude), float(longitude)
    except ValueError:
        return "Latitude and longitude must be numeric."

    # Get forecast URL from points API
    points_url = f"{NWS_API_BASE}/points/{lat},{lon}"
    points_data = await make_nws_request(points_url)

    if not points_data:
        return "Unable to fetch forecast data for this location."

    forecast_url = (points_data.get("properties") or {}).get("forecast")
    if not forecast_url:
        return "Forecast URL not available for this location."

    # Get forecast data
    forecast_data = await make_nws_request(forecast_url)
    if not forecast_data:
        return "Unable to fetch detailed forecast."

    periods = (forecast_data.get("properties") or {}).get("periods") or []
    if not periods:
        return "No forecast periods available."

    # Format first 5 periods
    forecasts = []
    for period in periods[:5]:
        name = period.get("name", "N/A")
        temp = period.get("temperature", "N/A")
        unit = period.get("temperatureUnit", "")
        detail = period.get("detailedForecast", "N/A")
        forecasts.append(f"{name}: {temp}°{unit}\n{detail}")

    return "\n---\n".join(forecasts)

@workflow(name="weather_mcp_workflow")
def start_server():
    """Start MCP server."""
    mcp.run(transport="streamable-http")

if __name__ == "__main__":
    try:
        start_server()
    except KeyboardInterrupt:
        sys.exit(0)

Etape suivante

Configuration des clients MCP

Configurez votre client MCP pour qu'il intègre les variables d'environnement d'observabilité.

Procédure

Modifiez votre fichier de configuration de Claude Desktop (son emplacement varie selon le système d'exploitation).
{
  "mcpServers": { 
    "Weather MCP Server": { 
      "command": "npx", 
      "args": ["mcp-remote", "http://localhost:8000/mcp"], 
      "env": { 
        "TRACELOOP_BASE_URL": "<instana-endpoint>", 
        "TRACELOOP_HEADERS": "x-instana-key=<agent-key>", 
        "OTEL_EXPORTER_OTLP_INSECURE": "true" 
      } 
    } 
  }
}
Remarque :

Pour obtenir des instructions de configuration, consultez la section « Connexion aux serveurs MCP locaux ».

GitHub Copilote

Pour configurer GitHub Copilot afin qu'il utilise votre serveur MCP, consultez GitHub Copilot MCP.

A propos de cette tâche

Remarque :

Ajoutez les variables d'environnement d'observabilité dans la section `env` de votre configuration.

Exécution de votre serveur MCP

A propos de cette tâche

Mode STDIO : en mode STDIO, le client MCP lance automatiquement le serveur en fonction de son fichier de configuration. Il vous suffit de lancer votre client (Claude Desktop, Copilot d' GitHub, etc.) et cela lancera le serveur en arrière-plan.

Remarque : certains clients n'affichent pas la balise racine tant que vous n'avez pas fermé la session. Pour Claude Desktop, fermez l'application après avoir reçu les réponses. Pour Copilot d' GitHub, arrêtez Copilot après avoir reçu les réponses.

Mode « Streamable » d' HTTP

Procédure

  1. Exporter les variables d'environnement d'observabilité.
    export TRACELOOP_BASE_URL=<instana-endpoint> 
    export TRACELOOP_HEADERS="x-instana-key=<agent-key>" 
    export OTEL_EXPORTER_OTLP_INSECURE=true
  2. Démarrez le serveur.
    python weather.py
  3. Redémarrez votre client MCP pour vous reconnecter avec la configuration mise à jour.

Modes de déploiement

Procédure

  • Mode agent : envoyer les traces via un agent d' Instana s local :
    export TRACELOOP_BASE_URL=localhost:4317
    export TRACELOOP_HEADERS="x-instana-key=<agent-key>"
    export OTEL_EXPORTER_OTLP_INSECURE=true
  • Mode sans agent : envoyer les traces directement au backend Instana :
    export TRACELOOP_BASE_URL=<instana-otlp-endpoint>:4317
    export TRACELOOP_HEADERS="x-instana-key=<agent-key>"
    export OTEL_EXPORTER_OTLP_INSECURE=false
    Remarque :

    Pour les points de terminaison du backend, consultez la section « Envoi de données d' OpenTelemetry s vers le backend Instana ».

Consulter les données sur Instana

Une fois que votre serveur MCP fonctionnera avec l'observabilité activée, les données s'afficheront dans le tableau de bord d'observabilité Gen AI d' Instana.

A propos de cette tâche

Figure 1. Traces de réponse de l'outil MCP
Traces de réponse de l'outil MCP
Figure 2. Outil météo Claude pour ordinateur de bureau
Outil météo Claude pour ordinateur de bureau

Pour plus d'informations sur la consultation et l'analyse des traces, consultez la section « Affichage des données de télémétrie ».

Traitement des incidents

Vous pourriez rencontrer les problèmes suivants avec MCP.

Aucune travée visible

  • Vérifiez que le service « OpenLLMetry » est installé :
    pip list | grep traceloop-sdk
  • Vérifiez que les variables d'environnement sont correctement définies.
  • Vérifiez si la fonction Traceloop.init() a été appelée avec succès.

Portées manquantes

Procédure
  • Assurez-vous que l'observabilité est activée à la fois sur le serveur et sur le client
  • Vérifier que les opérations MCP sont bien en cours d'exécution
  • Vérifiez les journaux de l'application pour voir s'il y a des erreurs ou des avertissements
Le client n'affiche pas la portée racine

Certains clients exigent que la session soit fermée avant l'affichage de la barre d'état.

Procédure
  • Claude Desktop : Quitter l'application après avoir reçu les réponses
  • GitHub Copilot : Arrêter Copilot après avoir reçu les réponses