Dépôt officiel : https://github.com/modelcontextprotocol/python-sdk
Vue d'ensemble
Le protocole MCP (Model Context Protocol) permet aux applications de fournir du contexte aux modèles de langage de manière normalisée. Ce SDK Python implémente les spécifications complètes du MCP, facilitant :
- La création de clients MCP connectables à n'importe quel serveur MCP
- Le dévelopement de serveurs exposant des ressources, prompts et outils
- L'utilisation de transports standards comme stdio et SSE
- La gestion des messages et événements du protocole MCP
Installation
Pour les projets utilisant uv :
uv add "mcp[cli]"
Avec pip :
pip install mcp
Lancer l'interface de développement MCP :
uv run mcp
Démarrage rapide
Exemple de serveur MCP minimal :
# serveur_demo.py
from mcp.server.fastmcp import FastMCP
# Initialisation du serveur
app = FastMCP("ApplicationDémonstration")
# Définition d'un outil de calcul
@app.tool()
def additionner(val1: int, val2: int) -> int:
"""Additionne deux valeurs entières"""
return val1 + val2
# Ressource dynamique de salutation
@app.resource("salutations://{identifiant}")
def obtenir_salutation(identifiant: str) -> str:
"""Retourne un message personnalisé"""
return f"Bonjour, {identifiant}!"
Exécution en mode développement :
mcp dev serveur_demo.py
Concepts fondamentaux du MCP
Le protocole MCP offre une architecture normalisée pour l'exposition de données et fonctionnalités aux LLM, comparable à des APIs web spécialisées. Les serveurs MCP permettent :
- Resources : Exposition de données (équivalent aux endpoints GET)
- Tools : Exécution d'actions (équivalent aux endpoints POST)
- Prompts : Définition de templates d'interaction réutilisables
Implémentation du serveur
Composant central gérant les connexions et le routage des messages :
from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from dataclasses import dataclass
from mcp.server.fastmcp import Context, FastMCP
# Configuration de base
serveur = FastMCP("MonService")
serveur = FastMCP("MonService", dependencies=["pandas", "numpy"])
# Gestion du cycle de vie avec contexte typé
@dataclass
class EtatApplication:
base_donnees: object
@asynccontextmanager
async def cycle_vie(serveur: FastMCP) -> AsyncIterator[EtatApplication]:
"""Gestion des ressources avec typage fort"""
connexion_db = await initialiser_base_donnees()
try:
yield EtatApplication(base_donnees=connexion_db)
finally:
await connexion_db.fermer()
# Intégration du cycle de vie
serveur = FastMCP("MonService", lifespan=cycle_vie)
# Utilisation dans un outil typé
@app.tool()
def interroger_donnees(ctx: Context) -> str:
"""Outil utilisant des ressources initialisées"""
base = ctx.request_context.lifespan_context["base_donnees"]
return base.requete()
Ressources (Resources)
Mécanisme d'exposition de données au LLM, similaire aux endpoints GET :
from mcp.server.fastmcp import FastMCP
app = FastMCP("ServiceDonnées")
# Ressource statique
@app.resource("config://application")
def parametres() -> str:
"""Configuration de l'application"""
return "Paramètres par défaut"
# Ressource dynamique
@app.resource("utilisateurs://{id_utilisateur}/donnees")
def profil_utilisateur(id_utilisateur: str) -> str:
"""Données utilisateur dynamiques"""
return f"Informations pour l'utilisateur {id_utilisateur}"
Outils (Tools)
Exécution d'opérations ou génération d'effets de bord :
import httpx
from mcp.server.fastmcp import FastMCP
app = FastMCP("ServiceCalculs")
# Outil synchrone
@app.tool()
def calculer_imc(masse_kg: float, taille_m: float) -> float:
"""Calcule l'indice de masse corporelle"""
return masse_kg / (taille_m ** 2)
# Outil asynchrone
@app.tool()
async def recuperer_meteo(ville: str) -> str:
"""Récupère la météo actuelle"""
async with httpx.AsyncClient() as client:
reponse = await client.get(f"https://api.meteo.com/{ville}")
return reponse.text
Templates d'interaction (Prompts)
Modèles réutilisables pour structurer les échanges avec le LLM :
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.prompts import base
app = FastMCP("ServicePrompts")
@app.prompt()
def analyser_code(source_code: str) -> str:
return f"Analyse demandée pour ce code :\n\n{source_code}"
@app.prompt()
def diagnostiquer_probleme(erreur: str) -> list[base.Message]:
return [
base.UserMessage("Message d'erreur rencontré :"),
base.UserMessage(erreur),
base.AssistantMessage("Je vais aider à résoudre ce problème. Quelles étapes avez-vous déjà tentées ?"),
]
Gestion des images
Traitement d'images via la classe intégrée :
from mcp.server.fastmcp import FastMCP, Image
from PIL import Image as PILImage
app = FastMCP("ServiceImages")
@app.tool()
def generer_apercu(chemin_image: str) -> Image:
"""Crée une miniature à partir d'une image"""
image_source = PILImage.open(chemin_image)
image_source.thumbnail((100, 100))
return Image(data=image_source.tobytes(), format="png")
Objet de contexte (Context)
Fournit l'accès aux fonctionnalités MCP pour les outils :
from mcp.server.fastmcp import FastMCP, Context
app = FastMCP("ServiceTraitement")
@app.tool()
async def traiter_fichiers(chemins: list[str], ctx: Context) -> str:
"""Traite une liste de fichiers avec suivi de progression"""
for position, chemin in enumerate(chemins):
ctx.info(f"Traitement de {chemin}")
await ctx.report_progress(position, len(chemins))
contenu, type_mime = await ctx.read_resource(f"fichier://{chemin}")
return "Traitement terminé"
Déploiement
Plusieurs méthodes d'exécution :
- Mode développement avec inspection :
mcp dev serveur.py - Intégration Claude Desktop :
mcp install serveur.py - Exécution directe :
python serveur.py - Montage ASGI :
application = Starlette(routes=[Mount('/', app=serveur.sse_app())])
Éléments fondamentaux du MCP
| Composant | Contrôleur | Description | Exemple |
|---|---|---|---|
| Prompts | Utilisateur | Templates d'interaction | Menu contextuel |
| Resources | Applictaion | Données de contexte | Fichier de configuration |
| Tools | Modèle | Exécution d'opérations | Appel d'API |
Capacités déclarées
Les serveurs MCP déclarent leurs capacités au démarrage : prompts, resources, tools, etc.