Votre LLM ne peut pas lire votre base de données. Ni appeler votre API interne. Ni exécuter du code sur votre machine. Avec MCP, en 50 lignes de Python, vous donnez à Claude (ou n'importe quel client compatible) un accès contrôlé à vos systèmes. Ce tutoriel MCP Python montre comment créer un serveur MCP avec FastMCP et l'intégrer à Claude Desktop — pas-à-pas, code prêt à copier-coller.
Modèle mental à garder en tête : un serveur MCP n'est pas une API classique. C'est une couche d'abstraction qui expose vos systèmes sous forme d'outils compréhensibles par un LLM — typés, documentés, invocables en langage naturel. Vous ne pensez plus en termes de routes REST, mais de capacités métier.
Créer un serveur MCP (Model Context Protocol) en Python 2026 : tutoriel FastMCP pas-à-pas
À qui s'adresse cet article ?
- Vous connaissez MCP dans les grandes lignes — sinon lisez d'abord notre guide MCP complet
- Vous voulez exposer vos données / API internes à Claude Desktop ou un autre client
- Vous maîtrisez Python basique (décorateurs, type hints) — pas besoin d'expertise async
TL;DR
- FastMCP = classe haut niveau du SDK officiel — un serveur en 10 lignes
- 3 primitives :
@mcp.tool(fonctions),@mcp.resource(données),@mcp.prompt(templates) - stdio pour Claude Desktop local, Streamable HTTP pour un serveur distant
- MCP Inspector pour tester sans connecter de LLM
- Validation Pydantic automatique via les type hints Python
1. Pourquoi créer son propre serveur MCP ?
Il existe déjà une centaine de serveurs MCP publics — filesystem, Postgres, GitHub, Slack, Google Drive. Pour 80 % des cas d'usage grand public, installer un serveur existant suffit. Mais dès que vous avez des données ou des APIs propres à votre organisation, créer votre propre serveur devient incontournable.
1.1 Trois cas où créer votre serveur
Exposer une base de données métier
Votre CRM interne, votre base produits, votre historique clients. Un tool search_customer donne à Claude un accès lecture contrôlé sans tout exporter.
Encapsuler une API interne
Votre API de facturation, votre système de tickets, vos webhooks. Claude n'a pas besoin de connaître vos endpoints — il voit des fonctions typées et documentées.
Agréger des sources hétérogènes
Un tool summarize_week qui combine Jira + Slack + emails. Vous contrôlez la logique de fusion ; Claude reçoit juste la réponse synthétisée.
1.2 Tools vs Resources vs Prompts — ce que vous allez exposer
| Primitive | Définition | Exemple |
|---|---|---|
| Tool | Fonction que le LLM peut invoquer avec des paramètres | search_orders(customer_id, limit) |
| Resource | Données en lecture seule identifiées par une URI | docs://readme.md |
| Prompt | Template de prompt paramétrable invocable par l'utilisateur | /review-pr pr_number=42 |
2. Architecture MCP — rappel express
MCP suit une architecture client-serveur. Le client (Claude Desktop, VS Code, Cursor, Zed, ou votre propre app) se connecte à un ou plusieurs serveurs MCP. Le protocole utilise JSON-RPC 2.0 sur trois transports possibles :
| Transport | Cas d'usage | Caractéristiques |
|---|---|---|
| stdio | Intégration locale (Claude Desktop, IDE) | Simple, pas d'infra — le client spawn le process |
| Streamable HTTP | Serveur distant, multi-client | Recommandé en prod — remplace l'ancien SSE |
| HTTP+SSE (legacy) | Ancien transport séparant endpoints requête/SSE | Déprécié, remplacé par Streamable HTTP (qui peut encore utiliser SSE en interne pour streamer plusieurs messages) |
Commencez par stdio. C'est le plus simple à développer et tester. Vous passerez à HTTP uniquement si vous devez partager le serveur en équipe ou l'exposer à plusieurs utilisateurs.
3. Setup — SDK MCP Python + FastMCP
Le SDK officiel Python s'installe en une commande. Utilisez uv (plus rapide que pip) ou un virtualenv classique :
# Option 1 : avec uv (recommandé, 10× plus rapide que pip)
uv init mon-serveur-mcp
cd mon-serveur-mcp
uv add "mcp[cli]" httpx
# Option 2 : avec venv classique
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# .venv\Scripts\activate # Windows
pip install "mcp[cli]" httpx
L'extra [cli] installe également les outils CLI associés (entre autres la commande mcp dev pour lancer/déboguer rapidement un serveur) — c'est la forme d'installation recommandée par la doc officielle MCP.
# Si vous n'avez pas besoin des outils CLI, mcp seul suffit
# pip install mcp
Le package mcp contient à la fois FastMCP (API haut niveau avec décorateurs) et les primitives bas niveau du protocole. Sauf cas avancé, utilisez toujours FastMCP — c'est 10× plus productif.
4. Premier serveur MCP en 10 lignes
Créez un fichier server.py. Voici un serveur MCP minimal qui expose un tool de calcul :
from mcp.server.fastmcp import FastMCP
# Instancier le serveur avec un nom
mcp = FastMCP("Mon Serveur Calcul")
@mcp.tool()
def addition(a: float, b: float) -> float:
"""Additionne deux nombres et retourne le résultat."""
return a + b
if __name__ == "__main__":
mcp.run() # stdio par défaut
C'est tout. Votre serveur expose un tool nommé addition avec deux paramètres typés. Le docstring devient la description vue par le LLM — soignez-le comme un message pour un collègue qui ne connaît pas le code.
Ce qui se passe en coulisse : FastMCP inspecte les type hints Python (a: float, b: float) et génère automatiquement un JSON Schema que Claude reçoit. Le docstring devient la description du tool. Zero boilerplate.
5. Exposer des tools — fonctions appelables par le LLM
Les tools sont le cœur de MCP. Passons à un exemple réaliste : un tool qui cherche des clients dans une base SQLite.
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
import sqlite3
mcp = FastMCP("CRM Search")
class Customer(BaseModel):
id: int
name: str
email: str
total_orders: int
@mcp.tool()
def search_customers(
query: str = Field(description="Recherche par nom ou email"),
limit: int = Field(default=10, ge=1, le=100),
) -> list[Customer]:
"""Recherche des clients par nom ou email.
Retourne une liste triée par nombre de commandes décroissant.
Limite à 100 résultats maximum pour éviter les gros retours.
"""
conn = sqlite3.connect("crm.db")
conn.row_factory = sqlite3.Row
cur = conn.execute(
"""SELECT id, name, email, total_orders FROM customers
WHERE name LIKE ? OR email LIKE ?
ORDER BY total_orders DESC LIMIT ?""",
(f"%{query}%", f"%{query}%", limit),
)
results = [Customer(**dict(r)) for r in cur.fetchall()]
conn.close()
return results
Points clés de cet exemple :
Field(description=...): ajoute une description fine par paramètre que Claude verrage=1, le=100: contraintes Pydantic qui protègent contre les abus- Retour typé
list[Customer]: FastMCP sérialise automatiquement en JSON - Requête paramétrée SQL : toujours utiliser des
?plutôt que du f-string — protection contre l'injection SQL même si c'est un LLM qui appelle
⚠️ Traiter le LLM comme une source hostile
Un LLM peut appeler un tool avec des paramètres absurdes ou malveillants — pas par malveillance intentionnelle, mais parce qu'il hallucine ou parce qu'un utilisateur a injecté un prompt en amont. Exemples réels :
limit=1000000qui fait exploser la mémoire serveur- Injection SQL indirecte via un paramètre
querymal filtré - Appels en boucle (retry LLM sur erreur → amplification DoS)
- Paramètres hors domaine métier (
customer_id=-1, dates futures impossibles)
Votre serveur MCP doit être conçu comme une API publique hostile, même s'il est utilisé en interne. Validation Pydantic stricte, rate limiting, timeouts agressifs, et logs de tout appel suspect.
5.1 Tool async pour les appels IO
Si votre tool appelle une API externe ou une DB async, déclarez-le async def — FastMCP gère le cycle asyncio pour vous :
import httpx
@mcp.tool()
async def fetch_weather(city: str) -> dict:
"""Récupère la météo actuelle pour une ville."""
async with httpx.AsyncClient(timeout=5.0) as client:
r = await client.get(f"https://wttr.in/{city}?format=j1")
r.raise_for_status()
data = r.json()
return {
"city": city,
"temp_c": int(data["current_condition"][0]["temp_C"]),
"desc": data["current_condition"][0]["weatherDesc"][0]["value"],
}
6. Exposer des resources — données lisibles
Les resources sont identifiées par des URI. Contrairement aux tools (appelés par le LLM), les resources sont lues par le client quand il en a besoin comme contexte.
@mcp.resource("config://server-info")
def get_server_info() -> str:
"""Informations de configuration du serveur."""
return """# Serveur MCP CRM DEV-AI
Version: 1.0
Base clients: 2 347 entrées
Dernière synchronisation: 22 avril 2026
"""
# Resource avec paramètre dynamique dans l'URI
@mcp.resource("customer://{customer_id}/profile")
def get_customer_profile(customer_id: str) -> str:
"""Profil détaillé d'un client (markdown formaté)."""
# ... lecture DB ...
return f"# Client {customer_id}\n\nNom: ...\nEmail: ..."
Les resources sont utiles quand l'utilisateur veut injecter du contexte dans la conversation (via un bouton "Attach resource" dans Claude Desktop), plutôt que de laisser le LLM décider d'appeler un tool.
7. Exposer des prompts — templates réutilisables
Les prompts sont des templates paramétrables que l'utilisateur déclenche explicitement. Selon le client MCP, ils peuvent être exposés comme commandes/raccourcis (par exemple des slash commands dans certains clients) — les clients ne supportent pas tous les primitives MCP de manière identique, consultez la matrice de support de votre client.
from mcp.server.fastmcp.prompts import base
@mcp.prompt()
def review_customer(customer_id: str) -> list[base.Message]:
"""Analyse complète d'un client : commandes, réclamations, recommandations."""
return [
base.UserMessage(
f"""Analyse le client {customer_id}. Utilise le tool search_customers
pour récupérer ses données, puis :
1. Résume son historique en 3 bullets
2. Identifie les risques potentiels (churn, litiges)
3. Propose 2 actions commerciales concrètes"""
)
]
L'utilisateur tape /review_customer customer_id=42 dans Claude Desktop, et le LLM reçoit un prompt structuré + les tools disponibles pour y répondre. C'est un pattern réutilisable qui capitalise votre expertise métier.
8. Tester avec MCP Inspector
Avant de connecter votre serveur à Claude Desktop, testez-le avec MCP Inspector — l'outil officiel de debug. Il lance une interface web qui se connecte à votre serveur et liste tous ses tools/resources/prompts.
# Mode stdio — Inspector lance lui-même le serveur
npx -y @modelcontextprotocol/inspector python server.py
# Mode Streamable HTTP — serveur déjà lancé séparément
# Terminal 1 :
python server.py # écoute sur http://localhost:8000
# Terminal 2 :
npx -y @modelcontextprotocol/inspector
# Dans l'UI Inspector → onglet Transport → Streamable HTTP
# URL : http://localhost:8000/mcp
# Dans les deux cas, l'interface ouvre http://localhost:5173
# Connect → liste des tools/resources/prompts, logs JSON-RPC en direct
L'option -y de npx auto-valide le téléchargement du package (utile en CI ou en première utilisation). Choisissez le mode selon votre transport cible : stdio pour un serveur local qui sera intégré à Claude Desktop, Streamable HTTP pour un serveur qui tournera en standalone.
Workflow conseillé : toujours tester avec Inspector avant d'intégrer à Claude Desktop. Vous gagnez un temps fou sur le debug — les erreurs dans Claude Desktop sont plus difficiles à diagnostiquer (logs cachés, silencieux en cas d'erreur de schema).
9. Intégrer à Claude Desktop
Une fois votre serveur testé, ajoutez-le à Claude Desktop en éditant claude_desktop_config.json.
Emplacement du fichier :
- macOS :
~/Library/Application Support/Claude/claude_desktop_config.json - Windows :
%APPDATA%\Claude\claude_desktop_config.json
Note : Claude Desktop est officiellement distribué pour macOS et Windows. Les builds Linux communautaires existent mais l'emplacement du fichier de config peut varier — consultez la documentation du build que vous utilisez.
// claude_desktop_config.json
{
"mcpServers": {
"crm-search": {
"command": "python",
"args": ["/chemin/absolu/vers/server.py"],
"env": {
"DATABASE_URL": "sqlite:///crm.db"
}
}
}
}
Redémarrez Claude Desktop. Votre serveur apparaît dans la barre inférieure (icône outil 🔨). Vous pouvez maintenant demander : "Cherche les clients qui ont 'Dupont' dans leur nom" — Claude appellera automatiquement search_customers.
10. Déployer en HTTP (Streamable HTTP)
Pour partager votre serveur avec une équipe, exposez-le en Streamable HTTP. C'est aussi simple qu'un mcp.run(transport="streamable-http") :
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("CRM Search", host="0.0.0.0", port=8000)
@mcp.tool()
def search_customers(query: str) -> list[dict]:
# ... même logique que précédemment ...
return []
if __name__ == "__main__":
mcp.run(transport="streamable-http")
Déployez ensuite derrière NGINX avec HTTPS + authentification (API key via header). Les clients MCP compatibles HTTP peuvent ensuite s'y connecter via l'URL https://mcp.votre-domaine.fr — consultez la doc de chaque client pour vérifier le support du transport HTTP/Streamable HTTP.
11. Sécurité — 4 règles d'or
Un serveur MCP expose vos données à un LLM, qui peut halluciner ou recevoir des prompts malveillants (prompt injection). Quatre règles non négociables :
⚠️ Ne jamais faire confiance aux paramètres envoyés par le LLM.
- Validation Pydantic stricte : contraintes
ge, le, pattern, max_lengthsur tous les paramètres - Scopes minimaux : un tool de lecture DB ne doit jamais pouvoir écrire. Utilisez un utilisateur DB read-only
- Rate limiting par session MCP : slowapi ou limiteur maison pour éviter qu'un LLM en boucle épuise vos ressources
- Logs structurés de chaque appel : ID session, tool appelé, paramètres, durée, résultat. Indispensable pour l'audit
Pour un déploiement HTTP, minimum vital : CORS restreint aux clients autorisés, HTTPS obligatoire (pas de HTTP en clair en production), et une forme d'authentification.
Authentification — niveaux de maturité :
- Minimum simple : API key par client via header — OK pour un serveur interne équipe
- Production multi-utilisateurs : la spec MCP définit un flow d'authorization basé sur OAuth 2.1 pour les serveurs protégés. Claude (via Claude Desktop et l'API Connectors) supporte ce flow pour les serveurs MCP distants. C'est la voie recommandée dès que vous avez plusieurs utilisateurs humains ou des permissions différenciées
- Multi-tenant B2B : OAuth 2.1 + scopes fins par tool (ex :
crm:readvscrm:write) + audit logs par session
Pour un premier serveur partagé en équipe, une API key suffit. Dès que vous visez un vrai serveur distant multi-utilisateurs, privilégiez le flow OAuth 2.1 défini par la spec MCP plutôt qu'une solution ad hoc — c'est ce que les clients MCP majeurs (Claude Desktop, Claude API Connectors) sont conçus pour consommer.
Ressources officielles MCP
- Spécification officielle : modelcontextprotocol.io
- SDK Python MCP : github.com/modelcontextprotocol/python-sdk
- MCP Inspector : github.com/modelcontextprotocol/inspector
- Serveurs de référence : github.com/modelcontextprotocol/servers
- Documentation Anthropic sur les connecteurs MCP : docs.anthropic.com
FAQ
Articles liés
Article
MCP : le standard Anthropic qui connecte les LLMs au monde réel
Guide conceptuel complet du Model Context Protocol — architecture, SDKs, serveurs populaires.
Lire l'article →Article
LangGraph 2026 : agents IA stateful en Python
Construisez des agents IA robustes avec mémoire persistante, cycles et outils — compatible MCP.
Lire l'article →Article
FastAPI streaming LLM Python 2026 — guide complet
SSE, WebSocket, OpenAI/Ollama/HuggingFace streaming avec FastAPI — TTFT, vLLM, NGINX.
Lire l'article →Formation
Formation LLM & IA Générative 2026
LLM, RAG, fine-tuning LoRA, agents IA LangChain — code Python complet gratuit.
Voir la formation →Cas d'usage métier concret
Dans un ATS (Applicant Tracking System) ou un CRM, un serveur MCP permet à un LLM d'interroger les candidats, scorer des profils selon une fiche de poste, ou générer des synthèses — sans exposer directement la base de données. Le LLM voit des tools métier (search_candidates(skills, seniority), score_match(candidate_id, job_id)) au lieu de requêtes SQL brutes. Résultat : un assistant de recrutement conversationnel, en Français, sur vos données internes, avec traçabilité complète des appels.
Consulting DEV-AI
Vous voulez exposer vos systèmes à Claude en toute sécurité ?
Conception d'architecture MCP, développement de serveurs sur mesure, audit sécurité, intégration Claude Desktop ou API. Accompagnement expert.
Contacter l'équipe →Newsletter IA
Restez à jour sur l'IA & le Machine Learning
Actus, tutos, outils — chaque semaine en français. Sans spam.