Créer Rapidement un Serveur MCP pour Claude Code

Audrey Lopez

Audrey Lopez

12 June 2025

Créer Rapidement un Serveur MCP pour Claude Code

Le Protocole de Contexte de Modèle (MCP) révolutionne la manière dont les assistants IA interagissent avec les outils externes et les sources de données. Considérez le MCP comme un port USB-C universel pour les applications IA – il offre un moyen standardisé de connecter Claude Code à pratiquement n'importe quelle source de données, API ou outil imaginable. Ce guide complet vous expliquera comment construire votre propre serveur MCP à partir de zéro, permettant à Claude Code d'accéder à des fonctionnalités personnalisées qui étendent ses capacités bien au-delà de ses fonctions intégrées.

Que vous souhaitiez intégrer des bases de données, des API, des systèmes de fichiers ou créer des outils entièrement personnalisés, le MCP constitue la base d'une extensibilité illimitée. À la fin de ce tutoriel, vous disposerez d'un serveur MCP opérationnel et comprendrez comment l'étendre pour n'importe quel cas d'utilisation.

💡
Vous voulez un excellent outil de test d'API qui génère une belle documentation d'API ?

Vous voulez une plateforme intégrée, Tout-en-Un, pour que votre équipe de développeurs travaille ensemble avec une productivité maximale ?

Apidog répond à toutes vos exigences et remplace Postman à un prix beaucoup plus abordable !
button

Qu'est-ce qu'un serveur MCP et pourquoi tout le monde en parle

Ce qui rend le MCP différent

Le MCP (Model Context Protocol) est un protocole ouvert développé par Anthropic qui permet aux modèles d'IA de communiquer avec des serveurs externes via une interface standardisée. Contrairement aux intégrations d'API traditionnelles où vous codez en dur des points d'accès spécifiques, le MCP offre un moyen structuré pour les assistants IA de découvrir, comprendre et utiliser des outils externes de manière dynamique.

Le génie du MCP réside dans sa découvrabilité. Lorsque Claude Code se connecte à votre serveur MCP, il apprend automatiquement quels outils sont disponibles, comment les utiliser et quels paramètres ils acceptent. Cela signifie que vous pouvez ajouter de nouvelles fonctionnalités sans mettre à jour Claude Code lui-même.

Architecture du MCP : Plongée en profondeur

Le protocole suit une architecture client-serveur avec des rôles clairement définis :

Flux de communication expliqué

Lorsque Claude Code a besoin d'utiliser un outil externe, voici ce qui se passe :

  1. Phase de découverte : Claude Code interroge votre serveur pour connaître les outils disponibles
  2. Validation du schéma : Votre serveur répond avec les définitions des outils et les schémas d'entrée
  3. Sélection de l'outil : Claude Code choisit les outils appropriés en fonction des requêtes de l'utilisateur
  4. Phase d'exécution : Claude Code envoie les appels d'outils avec les paramètres validés
  5. Traitement des résultats : Votre serveur traite la requête et renvoie des résultats structurés

Ce flux garantit la sécurité des types, une gestion appropriée des erreurs et un comportement cohérent sur toutes les intégrations MCP.

Prérequis et configuration de l'environnement

Analyse des exigences système

Avant de construire votre serveur MCP, vous devez comprendre votre environnement de développement et choisir les bons outils. Les serveurs MCP peuvent être construits dans plusieurs langages, mais Python et TypeScript sont les plus couramment pris en charge avec des outils étendus.

Pour le développement Python :

Pour le développement TypeScript/JavaScript :

Dépendances principales :

Préparation de l'environnement étape par étape

1. Installer l'interface en ligne de commande (CLI) de Claude Code

La CLI Claude Code est votre outil principal pour gérer les serveurs MCP. Installez-la globalement pour garantir l'accès depuis n'importe quel répertoire :

# Installer Claude Code globalement
npm install -g @anthropic-ai/claude-code

Pourquoi l'installation globale est importante : L'installation globale garantit que la commande claude est disponible à l'échelle du système, évitant les problèmes de chemin lors de l'enregistrement des serveurs MCP depuis différents répertoires.

2. Vérifier l'installation

Vérifiez que Claude Code est correctement installé et accessible :

# Vérifier l'installation et la version
claude --version

# Vérifier les commandes disponibles
claude --help

3. Configuration critique des permissions initiales

Cette étape est absolument essentielle et souvent négligée :

# Exécuter la configuration initiale avec contournement des permissions
claude --dangerously-skip-permissions

Ce que fait cette commande :

Pourquoi c'est requis : Sans cette étape, les serveurs MCP ne peuvent pas établir de connexions sécurisées avec Claude Code, ce qui entraîne des échecs d'authentification et des délais de connexion.

Considérations de sécurité : L'indicateur --dangerously-skip-permissions est sûr pour les environnements de développement mais contourne les invites de sécurité normales. Dans les environnements de production, examinez attentivement chaque demande de permission.

Configuration critique : Comprendre les portées (Scopes) du MCP

Pourquoi les portées de configuration sont importantes

L'un des pièges les plus courants lors de la construction de serveurs MCP est une gestion incorrecte de la portée de configuration. Comprendre les portées est crucial car elles déterminent où et quand votre serveur MCP est disponible pour Claude Code. De nombreux développeurs passent des heures à déboguer des erreurs "serveur introuvable" qui proviennent d'une mauvaise configuration de la portée.

Claude Code utilise un système de configuration hiérarchique conçu pour offrir de la flexibilité tout en maintenant la sécurité. Chaque portée sert un objectif spécifique et a des cas d'utilisation différents.

Hiérarchie des portées de configuration expliquée

1. Portée du projet (.mcp.json) - Priorité la plus élevée

Emplacement : Répertoire racine du projet dans un fichier .mcp.json

Objectif : Serveurs MCP spécifiques au projet qui ne doivent être disponibles que lors du travail dans ce projet spécifique

Cas d'utilisation : Connexions de base de données spécifiques à un projet, linters spécifiques au projet ou outils de construction personnalisés

Quand la portée du projet est appropriée :

2. Portée utilisateur (-scope user) - Configuration globale

Emplacement : Configuration du répertoire personnel de l'utilisateur

Objectif : Serveurs MCP disponibles globalement sur tous les projets et répertoires

Cas d'utilisation : Outils à usage général comme les API météo, les outils de calcul ou les utilitaires système

Pourquoi la portée utilisateur est généralement préférée :

3. Portée locale (par défaut) - Spécifique au répertoire

Emplacement : Contexte du répertoire de travail actuel

Objectif : Configurations rapides et temporaires de serveurs MCP

Limitation : Ne fonctionne que lorsque vous exécutez Claude Code depuis ce répertoire spécifique

Erreurs de configuration courantes

❌ Mauvaise approche (Portée locale - fonctionnalité limitée) :

claude mcp add my-server python3 /path/to/server.py

Problème : Ce serveur ne fonctionne que lorsque vous êtes dans le répertoire exact où vous l'avez enregistré.

✅ Approche correcte (Portée utilisateur - accès global) :

claude mcp add --scope user my-server python3 /path/to/server.py

Avantage : Ce serveur fonctionne depuis n'importe quel répertoire de votre système.

Planification stratégique des répertoires

Structure de répertoire recommandée

Créez une structure de répertoire bien organisée pour une maintenabilité à long terme :

# Créer un emplacement de stockage permanent
mkdir -p ~/.claude-mcp-servers/

# Organiser par fonctionnalité
mkdir -p ~/.claude-mcp-servers/apis/
mkdir -p ~/.claude-mcp-servers/utilities/
mkdir -p ~/.claude-mcp-servers/development/

Avantages d'une structure organisée

Maintenabilité : Facile à trouver et à mettre à jour les serveurs plus tard

Sécurité : Séparation claire entre différents types d'outils

Sauvegarde : Simple de sauvegarder tous les serveurs MCP en sauvegardant un seul répertoire

Partage : Facile de partager les configurations de serveur avec les membres de l'équipe

Guide de dépannage des portées

Diagnostiquer les problèmes de portée

Si votre serveur MCP n'apparaît pas, suivez cette séquence de diagnostic :

  1. Vérifier la configuration de la portée actuelle :
claude mcp list

  1. Vérifier que vous n'êtes pas dans un répertoire avec une portée de projet conflictuelle :
ls .mcp.json

  1. Tester depuis différents répertoires :
cd ~ && claude mcp list
cd /tmp && claude mcp list

Résoudre les problèmes de portée

Problème : Le serveur ne fonctionne que dans un seul répertoire

Solution : Supprimer la configuration locale et la rajouter avec la portée utilisateur

# Supprimer la configuration locale problématique
claude mcp remove my-server

# Rajouter avec la portée utilisateur globale
claude mcp add --scope user my-server python3 /path/to/server.py

Construire votre premier serveur MCP

Comprendre le processus de développement

Construire un serveur MCP implique de comprendre à la fois le protocole MCP et les exigences spécifiques de votre cas d'utilisation. Nous commencerons par un serveur "Hello World" de base pour comprendre les fondamentaux, puis nous construirons sur cette base.

Le processus de développement suit ces phases :

  1. Configuration de la structure du serveur : Créer la structure de fichiers de base et le point d'entrée
  2. Implémentation du protocole : Implémenter les méthodes MCP requises
  3. Définition des outils : Définir les outils que votre serveur fournit
  4. Enregistrement et test : Ajouter le serveur à Claude Code et vérifier la fonctionnalité
  5. Amélioration et production : Ajouter des fonctionnalités réelles et la gestion des erreurs

Étape 1 : Fondations et structure du projet

Créer l'environnement de développement

Tout d'abord, établissez un environnement de développement approprié pour votre serveur MCP :

# Naviguer vers votre répertoire de serveurs MCP
cd ~/.claude-mcp-servers/

# Créer un nouveau projet de serveur
mkdir my-first-server
cd my-first-server

# Initialiser la structure du projet
touch server.py
touch requirements.txt
touch .env

Pourquoi cette structure est importante

Développement organisé : Garder chaque serveur dans son propre répertoire évite les conflits et facilite la maintenance.

Isolation des dépendances : Chaque serveur peut avoir ses propres exigences sans affecter les autres.

Gestion de la configuration : Les fichiers d'environnement permettent une configuration sécurisée sans coder en dur les valeurs.

Comprendre les exigences du serveur MCP

Chaque serveur MCP doit implémenter trois méthodes JSON-RPC principales :

  1. initialize : Établit la connexion et déclare les capacités du serveur
  2. tools/list : Renvoie les outils disponibles et leurs schémas
  3. tools/call : Exécute des outils spécifiques avec les paramètres fournis

Étape 2 : Implémenter le framework serveur de base

Créez un fichier nommé server.py avec le modèle de base du serveur MCP :

#!/usr/bin/env python3
"""
Serveur MCP personnalisé pour l'intégration de Claude Code
"""

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

# Assurer une sortie non bufferisée pour une communication MCP correcte
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)

def send_response(response: Dict[str, Any]):
    """Envoyer une réponse JSON-RPC à Claude Code"""
    print(json.dumps(response), flush=True)

def handle_initialize(request_id: Any) -> Dict[str, Any]:
    """Gérer le handshake d'initialisation MCP"""
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "protocolVersion": "2024-11-05",
            "capabilities": {
                "tools": {}
            },
            "serverInfo": {
                "name": "my-custom-server",
                "version": "1.0.0"
            }
        }
    }

def handle_tools_list(request_id: Any) -> Dict[str, Any]:
    """Lister les outils disponibles pour Claude Code"""
    tools = [
        {
            "name": "hello_world",
            "description": "Un simple outil de démonstration",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Nom à saluer"
                    }
                },
                "required": ["name"]
            }
        }
    ]

    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "tools": tools
        }
    }

def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
    """Exécuter les appels d'outils depuis Claude Code"""
    tool_name = params.get("name")
    arguments = params.get("arguments", {})

    try:
        if tool_name == "hello_world":
            name = arguments.get("name", "World")
            result = f"Bonjour, {name} ! Votre serveur MCP fonctionne parfaitement."
        else:
            raise ValueError(f"Outil inconnu : {tool_name}")

        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "content": [
                    {
                        "type": "text",
                        "text": result
                    }
                ]
            }
        }
    except Exception as e:
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "error": {
                "code": -32603,
                "message": str(e)
            }
        }

def main():
    """Boucle serveur principale gérant la communication JSON-RPC"""
    while True:
        try:
            line = sys.stdin.readline()
            if not line:
                break

            request = json.loads(line.strip())
            method = request.get("method")
            request_id = request.get("id")
            params = request.get("params", {})

            if method == "initialize":
                response = handle_initialize(request_id)
            elif method == "tools/list":
                response = handle_tools_list(request_id)
            elif method == "tools/call":
                response = handle_tool_call(request_id, params)
            else:
                response = {
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32601,
                        "message": f"Méthode introuvable : {method}"
                    }
                }

            send_response(response)

        except json.JSONDecodeError:
            continue
        except EOFError:
            break
        except Exception as e:
            if 'request_id' in locals():
                send_response({
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32603,
                        "message": f"Erreur interne : {str(e)}"
                    }
                })

if __name__ == "__main__":
    main()

Explication de l'architecture du code

Configuration d'entrée/sortie : Les premières lignes configurent l'E/S non bufferisée, ce qui est critique pour la communication MCP. La sortie bufferisée peut entraîner des retards de livraison des messages qui rompent le protocole.

Gestion JSON-RPC : La boucle principale lit les requêtes JSON-RPC depuis stdin et écrit les réponses sur stdout. Cela suit la spécification MCP pour la communication serveur locale.

Stratégie de gestion des erreurs : Le code implémente plusieurs couches de gestion des erreurs :

Conformité au protocole : Chaque réponse inclut le champ requis jsonrpc: "2.0" et l'ID de requête pour une corrélation appropriée.

Étape 3 : Préparation et test du serveur

Rendre le serveur exécutable

# Rendre le serveur exécutable
chmod +x server.py

Pourquoi les permissions d'exécution sont importantes : Les serveurs MCP sont lancés comme des sous-processus par Claude Code. Sans permissions d'exécution, le lancement échouera avec des erreurs de permission cryptiques.

Test manuel du protocole

Avant de vous enregistrer auprès de Claude Code, testez l'implémentation du protocole du serveur :

# Tester le handshake d'initialisation
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | python3 server.py

À quoi s'attendre : Vous devriez voir une réponse JSON contenant la version du protocole et les capacités. Si vous voyez des messages d'erreur ou aucune sortie, vérifiez votre installation Python et la syntaxe du script.

Étapes de validation

Effectuez ces vérifications de validation avant de continuer :

  1. Vérification de syntaxe : python3 -m py_compile server.py
  2. Test d'importation : python3 -c "import json, sys, os"
  3. Test d'exécution : Vérifiez que le test manuel du protocole fonctionne

Étape 4 : Enregistrement auprès de Claude Code

Ajouter votre serveur

Enregistrez votre serveur en utilisant la portée appropriée et les chemins absolus :

# Enregistrer avec la portée utilisateur globale pour un accès universel
claude mcp add --scope user my-first-server python3 ~/.claude-mcp-servers/my-first-server/server.py

Détails critiques :

Vérification et dépannage

# Vérifier l'enregistrement
claude mcp list

# Vérifier les problèmes de connexion
claude mcp get my-first-server

Problèmes d'enregistrement courants :

Exemple avancé : Intégration d'une API météo

Aller au-delà de 'Hello World'

Maintenant que vous comprenez la structure de base d'un serveur MCP, construisons un serveur plus pratique qui démontre des modèles d'intégration réels. Ce serveur d'API météo vous apprendra :

Planifier votre intégration d'API

Avant d'écrire du code, considérez ces aspects d'intégration :

Sélection de l'API : Nous utiliserons l'API OpenWeatherMap pour sa simplicité et son niveau gratuit

Flux de données : Requête utilisateur → Validation des paramètres → Appel API → Formatage de la réponse → Réponse Claude

Scénarios d'erreur : Échecs réseau, clés API invalides, réponses mal formées, limitation de débit

Sécurité : Clés API stockées dans des variables d'environnement, assainissement des entrées

Stratégie d'implémentation

Construisons ce serveur de manière incrémentale, en implémentant chaque partie avec une gestion complète des erreurs :

#!/usr/bin/env python3
import json
import sys
import os
import requests
from typing import Dict, Any

# Configuration - utiliser des variables d'environnement pour la sécurité
WEATHER_API_KEY = os.environ.get("OPENWEATHER_API_KEY", "your-api-key-here")

def get_weather(city: str) -> str:
    """Récupérer les données météo actuelles pour une ville spécifiée"""
    try:
        url = "<http://api.openweathermap.org/data/2.5/weather>"
        params = {
            "q": city,
            "appid": WEATHER_API_KEY,
            "units": "metric"
        }
        response = requests.get(url, params=params, timeout=10)
        data = response.json()

        if response.status_code == 200:
            temp = data["main"]["temp"]
            desc = data["weather"][0]["description"]
            humidity = data["main"]["humidity"]
            return f"Météo à {city}: {temp}°C, {desc.title()}, Humidité: {humidity}%"
        else:
            return f"Erreur lors de la récupération de la météo : {data.get('message', 'Erreur inconnue')}"
    except requests.RequestException as e:
        return f"Erreur réseau : {str(e)}"
    except Exception as e:
        return f"Erreur lors du traitement des données météo : {str(e)}"

def handle_tools_list(request_id: Any) -> Dict[str, Any]:
    """Liste d'outils améliorée avec fonctionnalité météo"""
    tools = [
        {
            "name": "get_weather",
            "description": "Obtenir les conditions météo actuelles pour n'importe quelle ville dans le monde",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "Nom de la ville (par exemple, 'Londres', 'Tokyo', 'New York')"
                    }
                },
                "required": ["city"]
            }
        }
    ]

    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "tools": tools
        }
    }

def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
    """Exécution d'outil améliorée avec fonctionnalité météo"""
    tool_name = params.get("name")
    arguments = params.get("arguments", {})

    try:
        if tool_name == "get_weather":
            city = arguments.get("city")
            if not city:
                raise ValueError("Le nom de la ville est requis")
            result = get_weather(city)
        else:
            raise ValueError(f"Outil inconnu : {tool_name}")

        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "content": [
                    {
                        "type": "text",
                        "text": result
                    }
                ]
            }
        }
    except Exception as e:
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "error": {
                "code": -32603,
                "message": str(e)
            }
        }

# Inclure la même fonction main() et les autres gestionnaires de l'exemple de base

Fonctionnalités avancées expliquées

Sécurité des variables d'environnement : La clé API est chargée à partir des variables d'environnement, jamais codée en dur. Cela empêche l'exposition accidentelle dans le contrôle de version.

Gestion robuste des erreurs : La fonction get_weather() gère plusieurs scénarios d'erreur :

Schéma d'outil amélioré : Le schéma de l'outil météo inclut des descriptions détaillées et des exemples, aidant Claude Code à comprendre comment utiliser l'outil efficacement.

Étape 5 : Gestion professionnelle des dépendances et de la configuration

Créer un fichier de dépendances (requirements) approprié

requests>=2.28.0
python-dotenv>=1.0.0

Stratégie de fixation de version : L'utilisation d'exigences de version minimale (>=) garantit la compatibilité tout en permettant les mises à jour de sécurité. Pour les serveurs de production, envisagez une fixation de version exacte.

Configuration sécurisée de l'environnement

Créez un fichier .env pour la gestion de la configuration :

# Configuration de l'API météo
OPENWEATHER_API_KEY=votre_vraie_cle_api_ici

# Configuration du serveur
MCP_LOG_LEVEL=INFO
MCP_DEBUG=false

# Optionnel : Limitation de débit
MCP_MAX_REQUESTS_PER_MINUTE=60

Bonnes pratiques de sécurité :

Installation et isolation des dépendances

# Créer un environnement virtuel pour l'isolation
python3 -m venv mcp-env
source mcp-env/bin/activate  # Sur Windows : mcp-env\\\\Scripts\\\\activate

# Installer les dépendances
pip install -r requirements.txt

# Vérifier l'installation
python3 -c "import requests; print('Dépendances installées avec succès')"

Pourquoi les environnements virtuels sont importants : L'isolation empêche les conflits de dépendances entre différents serveurs MCP et votre installation Python système.

Tester et déboguer votre serveur MCP

Stratégie de test complète

Le test des serveurs MCP nécessite une approche multicouche car vous avez affaire à la fois à la conformité au protocole et à la correction fonctionnelle. Une stratégie de test systématique empêche les problèmes d'atteindre la production et facilite grandement le débogage.

Pyramide de test pour les serveurs MCP

  1. Tests unitaires : Test de fonctions individuelles
  2. Tests de protocole : Vérification de la conformité JSON-RPC
  3. Tests d'intégration : Test d'interaction avec Claude Code
  4. Tests de bout en bout : Validation du flux de travail complet

Couche 1 : Test manuel du protocole

Tester les méthodes MCP de base

Avant toute intégration, vérifiez que votre serveur implémente correctement le protocole MCP :

# Tester le handshake d'initialisation
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | python3 server.py

Structure de réponse attendue :

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {"tools": {}},
    "serverInfo": {"name": "your-server", "version": "1.0.0"}
  }
}

Tester la découverte d'outils

# Tester le point d'accès de liste d'outils
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | python3 server.py

Liste de vérification de validation :

Tester l'exécution d'outils

# Tester la fonctionnalité réelle de l'outil
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_weather","arguments":{"city":"London"}}}' | python3 server.py

Ce qu'il faut vérifier :

Couche 2 : Framework de test automatisé

Créer des scripts de test

Créez un fichier test_server.py pour les tests automatisés :

#!/usr/bin/env python3
import json
import subprocess
import sys

def test_mcp_method(method, params=None):
    """Tester une méthode MCP spécifique"""
    request = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": method,
        "params": params or {}
    }

    try:
        result = subprocess.run(
            [sys.executable, "server.py"],
            input=json.dumps(request),
            capture_output=True,
            text=True,
            timeout=10
        )
        return json.loads(result.stdout.strip())
    except Exception as e:
        return {"error": str(e)}

# Suite de tests
tests = [
    ("initialize", None),
    ("tools/list", None),
    ("tools/call", {"name": "hello_world", "arguments": {"name": "Test"}})
]

for method, params in tests:
    response = test_mcp_method(method, params)
    print(f"Testing {method}: {'✓ PASS' if 'result' in response else '✗ FAIL'}")

Couche 3 : Test d'intégration avec Claude Code

Enregistrement et vérification du serveur

# Enregistrer votre serveur
claude mcp add --scope user test-server python3 /full/path/to/server.py

# Vérifier l'enregistrement
claude mcp list | grep test-server

# Vérifier la santé du serveur
claude mcp get test-server

Test d'intégration en direct

# Démarrer Claude Code en mode test
claude

# Dans Claude Code, tester la découverte d'outils
/mcp

# Tester l'exécution d'outils
mcp__test-server__hello_world name:"Integration Test"

Modèle de nommage d'outils : Claude Code préfixe les outils avec mcp__<nom-serveur>__<nom-outil> pour éviter les conflits de noms.

Techniques de débogage avancées

Activer la journalisation de débogage

Ajoutez une journalisation complète à votre serveur :

import logging
import sys

# Configurer la journalisation vers stderr (n'interférera pas avec JSON-RPC)
logging.basicConfig(
    level=logging.DEBUG,
    stream=sys.stderr,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

logger = logging.getLogger(__name__)

def handle_tool_call(request_id, params):
    logger.debug(f"Appel d'outil reçu : {params}")
    # ... votre logique d'outil
    logger.debug(f"Exécution de l'outil terminée avec succès")

Analyse des journaux du serveur MCP

Claude Code maintient des journaux pour chaque serveur MCP :

# Afficher les journaux récents (macOS)
tail -f ~/Library/Logs/Claude/mcp-server-*.log

# Afficher les journaux récents (Linux)
tail -f ~/.config/claude/logs/mcp-server-*.log

# Rechercher les erreurs
grep -i error ~/Library/Logs/Claude/mcp-server-*.log

Modèles de débogage courants

Problème : Le serveur démarre mais les outils n'apparaissent pas

Diagnostic : Vérifier le format de la réponse tools/list

Solution : Valider la conformité au schéma JSON

Problème : Les appels d'outils échouent silencieusement

Diagnostic : Vérifier la gestion des erreurs dans tools/call

Solution : Ajouter une gestion complète des exceptions

Problème : La connexion serveur est interrompue

Diagnostic : Vérifier l'E/S non bufferisée et la gestion appropriée des exceptions

Solution : Vérifier la configuration de sys.stdout et la gestion des erreurs dans la boucle principale

Tests de performance et de fiabilité

Test de charge de votre serveur

# Tester plusieurs requêtes rapides
for i in {1..10}; do
  echo '{"jsonrpc":"2.0","id":'$i',"method":"tools/list","params":{}}' | python3 server.py &
done
wait

Surveillance de la mémoire et des ressources

# Surveiller l'utilisation des ressources du serveur
python3 -m memory_profiler server.py

# Vérifier les fuites de mémoire pendant un fonctionnement prolongé
python3 -m tracemalloc server.py

Dépannage des problèmes courants

Problèmes au niveau du protocole

  1. Réponses JSON invalides : Utiliser json.loads() pour valider la sortie
  2. Champs requis manquants : Vérifier la conformité à la spécification MCP
  3. Codes d'erreur incorrects : Utiliser les codes d'erreur JSON-RPC standard

Problèmes d'intégration

  1. Serveur n'apparaissant pas : Vérifier les permissions de fichier et le chemin Python
  2. Outils non accessibles : Vérifier la configuration et l'enregistrement de la portée
  3. Échecs d'authentification : Assurer une initialisation MCP appropriée

Bonnes pratiques et considérations de sécurité

Gestion des erreurs prête pour la production

Implémenter une validation robuste

La gestion des erreurs dans les serveurs MCP doit être complète car les échecs peuvent rompre toute la chaîne de communication avec Claude Code. Implémentez la validation à plusieurs niveaux :

def validate_arguments(arguments: Dict[str, Any], required: List[str]):
    """Valider que les arguments requis sont présents"""
    missing = [field for field in required if field not in arguments]
    if missing:
        raise ValueError(f"Champs requis manquants : {', '.join(missing)}")

def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
    """Exécution d'outil avec validation appropriée"""
    try:
        tool_name = params.get("name")
        arguments = params.get("arguments", {})

        # Valider avant de traiter
        if tool_name == "get_weather":
            validate_arguments(arguments, ["city"])

        # Traiter la logique de l'outil ici

    except ValueError as ve:
        return create_error_response(request_id, -32602, str(ve))
    except Exception as e:
        return create_error_response(request_id, -32603, f"Erreur interne : {str(e)}")

Standards de réponse aux erreurs

Suivez les conventions de code d'erreur JSON-RPC 2.0 :

Framework de sécurité complet

1. Gestion des secrets

Ne jamais coder en dur les informations sensibles. Utilisez une approche multicouche pour la configuration :

import os
from pathlib import Path

def load_config():
    """Charger la configuration avec hiérarchie de repli"""
    # 1. Variables d'environnement (priorité la plus élevée)
    api_key = os.environ.get("API_KEY")

    # 2. Fichier .env local
    if not api_key:
        env_path = Path(".env")
        if env_path.exists():
            # Charger depuis le fichier .env
            pass

    # 3. Trousseau système (production)
    if not api_key:
        try:
            import keyring
            api_key = keyring.get_password("mcp-server", "api_key")
        except ImportError:
            pass

    if not api_key:
        raise ValueError("Clé API introuvable dans aucune source de configuration")

    return {"api_key": api_key}

2. Assainissement et validation des entrées

Implémentez une validation stricte des entrées pour prévenir les attaques par injection :

import re
from typing import Any, Dict

def sanitize_string_input(value: str, max_length: int = 100) -> str:
    """Assainir les entrées de chaîne de caractères"""
    if not isinstance(value, str):
        raise ValueError("Entrée de chaîne de caractères attendue")

    # Supprimer les caractères potentiellement dangereux
    sanitized = re.sub(r'[<>"\\\\']', '', value)

    # Limiter la longueur pour prévenir les attaques DoS
    if len(sanitized) > max_length:
        raise ValueError(f"Entrée trop longue (max {max_length} caractères)")

    return sanitized.strip()

def validate_city_name(city: str) -> str:
    """Valider l'entrée du nom de ville"""
    sanitized = sanitize_string_input(city, 50)

    # Autoriser uniquement les lettres, espaces et ponctuation courante
    if not re.match(r'^[a-zA-Z\\\\s\\\\-\\\\.]+$', sanitized):
        raise ValueError("Format de nom de ville invalide")

    return sanitized

3. Limitation de débit et protection des ressources

Implémentez la limitation de débit pour prévenir les abus :

import time
from collections import defaultdict
from threading import Lock

class RateLimiter:
    def __init__(self, max_requests: int = 60, window_seconds: int = 60):
        self.max_requests = max_requests
        self.window_seconds = window_seconds
        self.requests = defaultdict(list)
        self.lock = Lock()

    def allow_request(self, client_id: str = "default") -> bool:
        """Vérifier si la requête est autorisée selon la limite de débit"""
        now = time.time()

        with self.lock:
            # Nettoyer les anciennes requêtes
            self.requests[client_id] = [
                req_time for req_time in self.requests[client_id]
                if now - req_time < self.window_seconds
            ]

            # Vérifier la limite
            if len(self.requests[client_id]) >= self.max_requests:
                return False

            # Enregistrer cette requête
            self.requests[client_id].append(now)
            return True

# Instance globale de limitation de débit
rate_limiter = RateLimiter()

Journalisation et surveillance avancées

Implémentation de la journalisation structurée

Utilisez la journalisation structurée pour un meilleur débogage et une meilleure surveillance :

import logging
import json
import sys
from datetime import datetime

class MCPFormatter(logging.Formatter):
    """Formateur personnalisé pour les journaux du serveur MCP"""

    def format(self, record):
        log_entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
        }

        # Ajouter un contexte supplémentaire si disponible
        if hasattr(record, 'tool_name'):
            log_entry["tool_name"] = record.tool_name
        if hasattr(record, 'request_id'):
            log_entry["request_id"] = record.request_id

        return json.dumps(log_entry)

# Configurer la journalisation structurée
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(MCPFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)

Surveillance des performances

Suivre les métriques de performance du serveur :

import time
import statistics
from collections import deque

class PerformanceMonitor:
    def __init__(self, max_samples: int = 1000):
        self.response_times = deque(maxlen=max_samples)
        self.error_count = 0
        self.request_count = 0

    def record_request(self, duration: float, success: bool):
        """Enregistrer les métriques de requête"""
        self.request_count += 1
        self.response_times.append(duration)

        if not success:
            self.error_count += 1

    def get_stats(self) -> Dict[str, Any]:
        """Obtenir les statistiques de performance actuelles"""
        if not self.response_times:
            return {"no_data": True}

        return {
            "total_requests": self.request_count,
            "error_rate": self.error_count / self.request_count,
            "avg_response_time": statistics.mean(self.response_times),
            "p95_response_time": statistics.quantiles(self.response_times, n=20)[18],
            "p99_response_time": statistics.quantiles(self.response_times, n=100)[98]
        }

# Moniteur de performance global
perf_monitor = PerformanceMonitor()

Stratégies de déploiement et de maintenance

Gestion des versions

Implémentez une gestion de version appropriée pour vos serveurs MCP :

__version__ = "1.2.3"
__mcp_version__ = "2024-11-05"

def get_server_info():
    """Renvoie les informations du serveur pour l'initialisation MCP"""
    return {
        "name": "my-production-server",
        "version": __version__,
        "mcp_protocol_version": __mcp_version__,
        "capabilities": ["tools", "resources"],  # Déclarer ce que vous supportez
    }

Implémentation de la vérification de santé (Health Check)

Ajoutez des capacités de vérification de santé pour la surveillance :

def handle_health_check(request_id: Any) -> Dict[str, Any]:
    """Point d'accès de vérification de santé pour la surveillance"""
    try:
        # Tester les fonctionnalités de base
        test_db_connection()  # Exemple de vérification de santé
        test_external_apis()  # Exemple de vérification de santé

        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "status": "healthy",
                "timestamp": datetime.utcnow().isoformat(),
                "version": __version__,
                "uptime_seconds": time.time() - start_time,
                "performance": perf_monitor.get_stats()
            }
        }
    except Exception as e:
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": {
                "status": "unhealthy",
                "error": str(e),
                "timestamp": datetime.utcnow().isoformat()
            }
        }

Gestion de l'arrêt progressif

Implémentez un nettoyage approprié lors de l'arrêt du serveur :

import signal
import sys

class MCPServer:
    def __init__(self):
        self.running = True
        self.active_requests = set()

        # Enregistrer les gestionnaires de signaux
        signal.signal(signal.SIGINT, self.shutdown_handler)
        signal.signal(signal.SIGTERM, self.shutdown_handler)

    def shutdown_handler(self, signum, frame):
        """Gérer l'arrêt progressif"""
        logger.info(f"Signal {signum} reçu, initialisation de l'arrêt progressif")
        self.running = False

        # Attendre que les requêtes actives se terminent
        timeout = 30  # secondes
        start_time = time.time()

        while self.active_requests and (time.time() - start_time) < timeout:
            time.sleep(0.1)

        logger.info("Arrêt terminé")
        sys.exit(0)

Cas d'utilisation réels et applications avancées

Modèles d'intégration d'entreprise

Les serveurs MCP excellent dans les environnements d'entreprise où Claude Code doit s'intégrer aux systèmes d'entreprise existants. Voici des modèles d'intégration éprouvés :

Serveurs d'intégration de bases de données

Automatisation des flux de travail de développement

Surveillance et opérations système

Modèles d'architecture avancés

Orchestration multi-serveurs

Pour les flux de travail complexes, concevez des serveurs MCP qui se coordonnent entre eux :

# Modèle de coordination de serveurs
def coordinate_workflow(workflow_id: str, steps: List[Dict]) -> Dict:
    """Coordonner un flux de travail en plusieurs étapes sur plusieurs serveurs"""
    results = {}

    for step in steps:
        server_name = step["server"]
        tool_name = step["tool"]
        params = step["params"]

        # Appeler un autre serveur MCP via Claude Code
        result = call_mcp_tool(server_name, tool_name, params)
        results[step["id"]] = result

        # Gérer les dépendances entre les étapes
        if step.get("depends_on"):
            inject_dependencies(params, results, step["depends_on"])

    return {"workflow_id": workflow_id, "results": results}

Mise en cache et optimisation des performances

Implémentez une mise en cache intelligente pour les données fréquemment demandées :

import hashlib
import pickle
from datetime import datetime, timedelta

class IntelligentCache:
    def __init__(self, default_ttl: int = 3600):
        self.cache = {}
        self.default_ttl = default_ttl

    def get_cache_key(self, tool_name: str, params: Dict) -> str:
        """Générer une clé de cache cohérente"""
        key_data = f"{tool_name}:{json.dumps(params, sort_keys=True)}"
        return hashlib.md5(key_data.encode()).hexdigest()

    def get(self, tool_name: str, params: Dict) -> Optional[Any]:
        """Obtenir le résultat mis en cache s'il est valide"""
        key = self.get_cache_key(tool_name, params)

        if key in self.cache:
            data, expiry = self.cache[key]
            if datetime.now() < expiry:
                return data
            else:
                del self.cache[key]

        return None

    def set(self, tool_name: str, params: Dict, result: Any, ttl: Optional[int] = None):
        """Mettre en cache le résultat avec TTL"""
        key = self.get_cache_key(tool_name, params)
        expiry = datetime.now() + timedelta(seconds=ttl or self.default_ttl)
        self.cache[key] = (result, expiry)

Stratégies de déploiement en production

Déploiement conteneurisé

Empaquetez votre serveur MCP sous forme de conteneur Docker pour un déploiement cohérent :

FROM python:3.11-slim

WORKDIR /app

# Installer les dépendances système
RUN apt-get update && apt-get install -y \\\\
    curl \\\\
    && rm -rf /var/lib/apt/lists/*

# Copier et installer les dépendances Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copier le code de l'application
COPY server.py .
COPY config/ ./config/

# Créer un utilisateur non root
RUN useradd -m -s /bin/bash mcpuser
USER mcpuser

# Vérification de santé
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\\\
    CMD python3 -c "import requests; requests.get('<http://localhost:8080/health>')"

CMD ["python3", "server.py"]

Déploiement Kubernetes

Déployez les serveurs MCP dans Kubernetes pour l'évolutivité et la fiabilité :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-weather-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mcp-weather-server
  template:
    metadata:
      labels:
        app: mcp-weather-server
    spec:
      containers:
      - name: mcp-server
        image: your-registry/mcp-weather-server:latest
        ports:
        - containerPort: 8080
        env:
        - name: OPENWEATHER_API_KEY
          valueFrom:
            secretKeyRef:
              name: mcp-secrets
              key: openweather-api-key
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

Considérations sur la mise à l'échelle et les performances

Modèles de mise à l'échelle horizontale

Concevez vos serveurs MCP pour prendre en charge la mise à l'échelle horizontale :

  1. Conception sans état (Stateless) : Maintenez les serveurs sans état pour permettre une réplication facile
  2. Équilibrage de charge (Load Balancing) : Distribuer les requêtes sur plusieurs instances de serveur
  3. Pooling de base de données : Utiliser le pooling de connexion pour les serveurs adossés à une base de données
  4. Stratégies de mise en cache : Implémenter Redis ou Memcached pour la mise en cache partagée

Techniques d'optimisation des performances

import asyncio
import aiohttp
from concurrent.futures import ThreadPoolExecutor

class HighPerformanceMCPServer:
    def __init__(self):
        self.executor = ThreadPoolExecutor(max_workers=10)
        self.session = None

    async def async_tool_call(self, tool_name: str, params: Dict) -> Dict:
        """Gérer les appels d'outils de manière asynchrone"""
        if not self.session:
            self.session = aiohttp.ClientSession()

        # Utiliser des opérations asynchrones pour les tâches liées aux E/S
        if tool_name == "web_search":
            return await self.async_web_search(params)
        elif tool_name == "database_query":
            return await self.async_database_query(params)
        else:
            # Utiliser un pool de threads pour les tâches liées au CPU
            loop = asyncio.get_event_loop()
            return await loop.run_in_executor(
                self.executor,
                self.sync_tool_call,
                tool_name,
                params
            )

Conclusion et prochaines étapes

Maîtriser le développement MCP

Construire des serveurs MCP pour Claude Code représente un changement de paradigme dans le développement d'applications IA. Contrairement aux intégrations d'API traditionnelles qui nécessitent des connexions codées en dur, le MCP offre une interface dynamique et découvrable qui rend les assistants IA véritablement extensibles.

Tout au long de ce guide complet, vous avez appris :

Compétences fondamentales :

Préparation à la production :

Capacités avancées :

Approche de développement stratégique

Phase 1 : Construction des fondations (Semaine 1-2)

Commencez par des serveurs simples, à usage unique, pour comprendre le protocole :

Phase 2 : Expansion de l'intégration (Semaine 3-4)

Construisez des serveurs plus complexes qui s'intègrent aux systèmes existants :

Phase 3 : Déploiement d'entreprise (Mois 2+)

Déployez des serveurs prêts pour la production avec un support opérationnel complet :

Stratégies de succès à long terme

Engagement communautaire

Amélioration continue

Opportunités d'innovation

L'avenir du développement MCP

Le Protocole de Contexte de Modèle représente la base d'un nouvel écosystème d'applications intégrées à l'IA. En construisant des serveurs MCP, vous ne créez pas seulement des outils pour Claude Code – vous construisez des composants réutilisables qui fonctionneront à travers l'écosystème croissant d'assistants IA compatibles MCP.

Votre investissement dans le développement MCP porte ses fruits grâce à :

Rappels critiques pour le succès

Alors que vous vous lancez dans votre parcours de développement MCP, rappelez-vous ces principes essentiels :

  1. Maîtrise de la portée de configuration : Utilisez toujours -scope user pour les serveurs de développement, sauf si vous avez spécifiquement besoin de restrictions au niveau du projet
  2. La sécurité d'abord : Ne jamais coder en dur les secrets, toujours valider les entrées, implémenter la limitation de débit
  3. Exhaustivité de la gestion des erreurs : Anticiper et gérer gracieusement tous les modes de défaillance
  4. Rigueur des tests : Tester la conformité au protocole, la fonctionnalité et l'intégration
  5. Qualité de la documentation : Documenter vos serveurs pour la collaboration d'équipe et la maintenance

Obtenir de l'aide et des ressources

Lorsque vous rencontrez des difficultés :

Commencez à construire dès aujourd'hui, itérez rapidement et rejoignez la communauté croissante de développeurs qui étendent les capacités de l'IA grâce au Protocole de Contexte de Modèle. Vos serveurs MCP personnalisés ouvriront de nouvelles possibilités pour les flux de travail assistés par l'IA que nous commençons à peine à imaginer.

N'oubliez pas : chaque intégration complexe a commencé par un simple serveur "Hello World". Commencez par les bases, maîtrisez les fondamentaux et construisez progressivement les outils intégrés à l'IA qui transformeront votre façon de travailler.

💡
Vous voulez un excellent outil de test d'API qui génère une belle documentation d'API ?

Vous voulez une plateforme intégrée, Tout-en-Un, pour que votre équipe de développeurs travaille ensemble avec une productivité maximale ?

Apidog répond à toutes vos exigences et remplace Postman à un prix beaucoup plus abordable !
button

Pratiquez le Design-first d'API dans Apidog

Découvrez une manière plus simple de créer et utiliser des API