Si vous êtes développeur Python ou TypeScript et souhaitez que Claude, GPT ou Cursor accèdent à vos bases de données, appellent des API ou lisent des fichiers, vous connaissez déjà la limite fondamentale : les modèles n'ont pas de mains intégrées. Les données d'entraînement ont une date de coupure et les modèles ne peuvent pas exécuter d'actions externes seuls. Ce guide vous mène d'un projet vide à un MCP Server prêt pour la production. Vous implémenterez Tools, Resources et Prompts, ferez tourner les transports stdio et HTTP+SSE, et déploierez avec Docker. À la fin, vous pourrez brancher votre toolchain dans Cursor ou Claude Desktop sur macOS. Les paliers de nœuds sont sur la page tarifs NOVAKVM.
[ SECTION_01 ] // WHAT_IS_MCP Qu'est-ce que MCP : du Function Calling au protocole d'outils unifié
L'intégration d'outils IA a suivi une trajectoire claire. Le Function Calling (OpenAI, 2023) a permis aux modèles d'émettre des charges JSON structurées. Les Plugins et GPT Actions ont encapsulé des endpoints HTTP en plugins de conversation. Le MCP (Model Context Protocol), open-sourcé par Anthropic en novembre 2024, standardise la découverte, la description et l'invocation d'outils par les modèles. Une seule implémentation suffit : Claude Desktop, Cursor, VS Code Continue et d'autres hôtes réutilisent le même serveur.
- Plafond de capacité des LLM : pas de données en temps réel, pas d'accès direct au système de fichiers ou à une base. Les outils externes fournissent les sens et les mains.
- Fragmentation des schémas : OpenAI Function Calling, Claude Tool Use et LangChain Agents définissent chacun des schémas d'outils différents. Changer de modèle ou d'IDE implique de réécrire des adaptateurs.
- Absence de découverte : une API REST traditionnelle n'indique pas à l'IA ce qu'elle peut faire. Les runtimes MCP exposent une liste de capacités via
tools/list. - Session et contexte : MCP maintient une connexion persistante pour les workflows Agent multi-étapes. Le REST sans état est plus difficile à enchaîner pour des tâches complexes.
- Sécurité et permissions : le serveur peut restreindre quels outils écrivent, quelles ressources sont en lecture seule, et bloquer les dépassements du modèle sur les données de production.
L'architecture client-serveur JSON-RPC se décompose ainsi :
- Host (hôte) : Claude Desktop, Cursor, VS Code — l'interface utilisateur.
- MCP Client : intégré à l'hôte ; maintient une session 1:1 avec chaque serveur.
- MCP Server (le vôtre) : expose trois primitives — Tools (actions exécutables), Resources (données en lecture seule), Prompts (modèles de prompt réutilisables).
- Transport : le dev local utilise stdio (stdin/stdout du processus enfant) ; le déploiement distant utilise HTTP + SSE (push Server-Sent Events).
- Protocole : tous les messages suivent JSON-RPC 2.0, par ex.
initialize→tools/list→tools/call→notifications/cancelled. - Cycle de vie : poignée de main → négociation des capacités → état stable → arrêt propre. Le client peut envoyer un
pingpour maintenir la session.
| Dimension | MCP | OpenAI FC | LangChain Tools |
|---|---|---|---|
| Standardisation | Protocole ouvert, multi-éditeur | Lié à l'API OpenAI | Format interne au framework |
| Découverte d'outils | tools/list à l'exécution |
Schéma embarqué par requête | Enregistrement statique en code |
| Resources / Prompts | Support natif | Non supporté | Encapsulation manuelle requise |
| Transport | stdio / HTTP+SSE | API HTTPS | Appels in-process |
| Intégration IDE native | Cursor, Claude Desktop, etc. | Écosystème plugins ChatGPT | Couche de pont nécessaire |
MCP ne répond pas à la question « peut-on appeler une API », mais à « comment l'IA découvre, sélectionne et invoque correctement les outils » — le problème central de l'ère Agent.
[ SECTION_02 ] // DEV_ENV Environnement de développement : SDK Python mcp vs SDK TypeScript
La stack officielle propose deux SDK de premier plan : le package Python mcp (avec l'API haut niveau FastMCP) et TypeScript @modelcontextprotocol/sdk. Python convient aux prototypes rapides et aux charges data/ML ; TypeScript s'intègre à l'écosystème Node.js et aux équipes frontend. Ce tutoriel centre sur Python FastMCP ; la structure TypeScript est symétrique. Sur un Mac mini M4, Python 3.12 préinstallé via Homebrew ou pyenv offre des performances stables pour le dev local.
mkdir my-mcp-server && cd my-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" httpx pydantic python-dotenv
npm install -g @modelcontextprotocol/inspector
Structure de projet recommandée :
my-mcp-server/
├── server.py
├── tools/
├── resources/
├── prompts/
├── tests/
├── Dockerfile
├── requirements.txt
└── .env
Trois outils pour le débogage et l'intégration hôte :
- MCP Inspector : débogueur visuel officiel. Liste tools, resources et prompts ; déclenche les appels manuellement.
- Claude Desktop : éditez
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) pour enregistrer un serveur stdio. - Cursor : Réglages → MCP → ajoutez la configuration serveur. Supporte stdio et endpoints HTTP distants.
[ SECTION_03 ] // HELLO_WORLD Hello World : lancer votre premier MCP Server en 10 lignes
FastMCP fournit un serveur minimal avec l'outil say_hello :
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("hello-server")
@mcp.tool()
def say_hello(name: str) -> str:
return f"Hello, {name}! MCP Server is running."
if __name__ == "__main__":
mcp.run()
Vérifiez avec Inspector :
npx @modelcontextprotocol/inspector python server.py
Ouvrez l'interface Inspector dans le navigateur. Dans le panneau Tools, appelez say_hello avec {"name": "NOVAKVM"}. Vous devriez recevoir le message de salutation.
Configuration Claude Desktop (claude_desktop_config.json) :
{
"mcpServers": {
"hello-server": {
"command": "/path/to/my-mcp-server/.venv/bin/python",
"args": ["/path/to/my-mcp-server/server.py"]
}
}
}
Configuration MCP Cursor : créez .cursor/mcp.json à la racine du projet, ou ajoutez un JSON équivalent dans Cursor → Réglages → MCP. Redémarrez Cursor. En mode Agent, l'outil say_hello doit apparaître.
[ SECTION_04 ] // TOOLS Tools en profondeur : cinq types d'outils et bonnes pratiques d'erreurs
Dans MCP, la signature de fonction fait office de documentation. Noms de paramètres, annotations de type et docstrings deviennent du JSON Schema pour le modèle. Utilisez des modèles Pydantic pour les entrées complexes :
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: str = Field(..., description="Mots-clés de recherche")
limit: int = Field(10, ge=1, le=100, description="Nombre max de résultats")
@mcp.tool()
async def search_docs(input: SearchInput) -> list[dict]:
...
Les serveurs de production implémentent généralement ces cinq catégories d'outils :
- calculator : évaluation sécurisée d'expressions mathématiques. Évitez
evalbrut ; parsez avecastou une bibliothèque dédiée. - file_read / file_write : restriction à un répertoire racine (style chroot) pour bloquer le path traversal. Les écritures peuvent exiger confirmation ou liste blanche d'extensions.
- fetch_url : requêtes HTTP asynchrones — exemple ci-dessous.
- db_query : SQL en lecture seule (
SELECT) avec requêtes paramétrées. Placez les écritures dans un outil séparé avec journal d'audit. - get_current_time : retourne un horodatage ISO 8601 pour que le modèle connaisse l'heure actuelle.
import httpx
@mcp.tool()
async def fetch_url(url: str, timeout: int = 30) -> str:
async with httpx.AsyncClient(timeout=timeout) as client:
resp = await client.get(url)
resp.raise_for_status()
return resp.text[:50000]
Bonnes pratiques de gestion d'erreurs :
- Capturez les exceptions dans les outils et retournez du texte d'erreur structuré plutôt que de faire crasher le processus. Le client renvoie le résultat au modèle pour retry ou stratégie alternative.
- Définissez des timeouts et limites de retry sur les API externes. Évitez les boucles d'appels infinies du modèle.
- Lisez clés API et chaînes de connexion uniquement depuis les variables d'environnement. Ne retournez jamais de secrets dans la sortie d'outil ou les Resources.
- Les outils d'écriture doivent retourner un résumé d'opération (ce qui a changé, lignes affectées) pour que le modèle confirme avec l'utilisateur.
[ SECTION_05 ] // RESOURCES Protocole Resources : données en lecture seule vs outils exécutables
Resource vs Tool : une Resource est un contexte en lecture seule (fichiers de config, profils utilisateur, extraits de logs). Le modèle la récupère via resources/read. Un Tool est une action exécutable (requête, écriture, appel HTTP). Les Resources conviennent aux informations que l'IA doit voir sans modifier.
Conventions de schéma URI :
config://app/settings— configuration statique enregistrée au démarrage.user://{id}/profile— modèle dynamique ; le client fournit un id et le serveur génère le contenu à la demande.file://— mappe le système de fichiers local (nécessite un bac à sable de chemins).
Les Resources supportent quatre catégories MIME : text/plain, application/json, blob binaire (encodé Base64) et stream (push par blocs pour les gros fichiers).
@mcp.resource("config://app/settings")
def get_app_settings() -> str:
return json.dumps({"env": "production", "version": "1.2.0"})
@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
profile = db.fetch_user(user_id)
return json.dumps(profile)
Un serveur de ressources filesystem peut enregistrer récursivement les fichiers d'un répertoire. L'IA voit la structure du projet et la config clé pendant le codage sans appeler un outil read par fichier.
[ SECTION_06 ] // PROMPTS Prompts : échafaudages de conversation multi-tours réutilisables
Un Prompt MCP est un modèle prédéfini que l'hôte peut lister et injecter dans la conversation. Utilisez-le pour la revue de code, les post-mortems d'incident, les revues de conception API et autres workflows répétitifs. Les Prompts acceptent des paramètres placeholder et supportent des structures de messages multi-tours.
from mcp.types import PromptMessage, TextContent
@mcp.prompt()
def code_review_prompt(language: str, focus: str = "security") -> list[PromptMessage]:
return [
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Examinez le code {language} suivant sous l'angle {focus}. Listez problèmes et améliorations :\n\n"
)
)
]
Exemple multi-tours : le premier tour fixe le rôle et les contraintes, le second injecte le placeholder de code, le troisième demande une sortie JSON structurée (severity / file / line / suggestion). Les équipes codifient les bonnes pratiques en Prompts pour que les nouveaux membres évitent de réécrire les system prompts.
[ SECTION_07 ] // HTTP_TRANSPORT Transport HTTP : du stdio au service distant Streamable HTTP
| Dimension | stdio | HTTP + SSE |
|---|---|---|
| Déploiement | Processus enfant local | Serveur distant / conteneur |
| Réseau | Aucun requis | Accessibilité publique ou privée |
| Scale horizontal | Machine unique | Load balancer + affinité de session |
| Authentification | Isolation de processus | Bearer Token / API Key |
| Cas d'usage | Dev personnel, Claude Desktop | Partage équipe, hébergement cloud 7j/7 |
FastMCP supporte le transport streamable-http. Basculez en une ligne :
if __name__ == "__main__":
mcp.run(transport="streamable-http", host="0.0.0.0", port=8080)
Les déploiements HTTP de production nécessitent ces couches :
- Bearer Token / API Key : validez l'en-tête
Authorizationau reverse proxy ou middleware. - CORS : si un Inspector navigateur traverse les origines, autorisez les domaines sources corrects.
- Rate limiting : limitez par IP ou clé API pour stopper les tempêtes d'appels pilotées par le modèle.
- TLS : l'exposition publique exige HTTPS. Terminez SSL avec Caddy ou Nginx.
[ SECTION_08 ] // DEBUG_TEST Débogage, tests et dépannage : Inspector, pytest et checklist en six étapes
Workflow MCP Inspector : après le lancement, le panneau gauche affiche l'arbre de capacités du serveur. Le panneau Tools accepte des paramètres JSON pour les appels manuels. Notifications montre les événements push du serveur. Logs affiche stderr. Inspector redémarre le processus enfant quand vous modifiez le code.
import pytest
from server import say_hello
def test_say_hello():
result = say_hello("World")
assert "Hello, World!" in result
@pytest.mark.asyncio
async def test_fetch_url():
result = await fetch_url("https://httpbin.org/get")
assert "origin" in result
| Symptôme | Cause probable | Correctif |
|---|---|---|
| Outils non listés | Décorateur manquant ou échec de démarrage serveur | Vérifiez stderr ; reconnectez Inspector |
| Erreur sérialisation JSON | Retour datetime, Decimal ou types non-JSON | Appelez json.dumps manuellement ou convertissez en str |
| Timeout d'appel | API externe lente, pas de timeout défini | Définissez timeout dans l'outil ; augmentez la limite côté client |
| Permission refusée | Chemin hors sandbox ou mauvaises credentials DB | Vérifiez ALLOWED_PATHS et .env |
Checklist de déploiement production en six étapes :
- Épingler les dépendances : exécutez
pip freeze > requirements.txt. Fixez Python et la version du SDK mcp en CI pour éviter les breaking changes upstream. - Rédiger un Dockerfile : build multi-étapes ; l'image finale ne contient que les dépendances runtime. Exécutez le serveur en utilisateur non-root.
- Configurer les variables d'environnement : clés API, chaînes de connexion DB et ALLOWED_PATHS passent par la gestion de secrets. Pas de hardcoding.
- Choisir une plateforme d'hébergement : Railway ou Render pour validation rapide ; AWS Lambda avec adaptateur HTTP pour appels peu fréquents ; Cloud Run ou VPS pour un service 7j/7 permanent.
- Ajouter le monitoring : logs JSON structurés, endpoint
/health, métriques Prometheus ou reporting d'exceptions Sentry. - Vérifier l'intégration Cursor / Claude : placez URL distante et Bearer Token dans la config MCP. Appelez
tools/listpour confirmer la liste complète avant déploiement.
[ SECTION_09 ] // PRODUCTION Mise en production : Docker, plateformes d'hébergement et observabilité
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
USER nobody
EXPOSE 8080
CMD ["python", "server.py"]
Options de plateforme d'hébergement :
- Railway / Render : déploiements par git push. Les tiers gratuits conviennent aux MVP. Surveillez l'impact du cold start sur les connexions SSE longues.
- AWS Lambda : facturation à l'invocation. Nécessite un adaptateur HTTP-to-stdio. Convient aux outils internes peu fréquents.
- Google Cloud Run : natif conteneur avec autoscaling. Définissez min-instances ≥ 1 pour maintenir les sessions SSE.
- VPS / bare metal : contrôle total réseau et disque. Idéal quand les données sensibles doivent rester on-premises. Un Mac mini M4 bare metal NOVAKVM évite la virtualisation et offre des I/O disque prévisibles pour les bases vectorielles.
Stack d'observabilité :
- Logging : structlog ou python-json-logger. Enregistrez nom d'outil, duration_ms et statut à chaque appel.
- Prometheus : exposez les compteurs
mcp_tool_calls_totalet histogrammesmcp_tool_duration_seconds. - Sentry : capturez les exceptions non gérées. Taguez avec la version serveur pour un rollback plus rapide.
Compatibilité des versions : la révision de spec MCP 2025-03-26 a introduit Streamable HTTP. Avant déploiement, confirmez que votre client (version Cursor, version Claude Desktop) et le SDK serveur supportent le même transport. Documentez les versions minimales dans le README, par ex. mcp>=1.2.0.
[ SECTION_10 ] // ECOSYSTEM Projet pratique : MCP base de connaissances ChromaDB, écosystème 2026 et parcours d'apprentissage
Projet de synthèse — un MCP Server base de connaissances : stockez les vecteurs de documents dans ChromaDB ou Qdrant, utilisez watchfiles pour ré-indexer lors des changements de répertoire, et exposez les outils search_knowledge et write_note. Branchez-le dans Cursor et l'agent peut rechercher la documentation d'équipe au lieu de s'appuyer uniquement sur les données d'entraînement. Sur Apple Silicon, l'inférence d'embeddings locale bénéficie de la mémoire unifiée du Mac mini M4.
@mcp.tool()
async def search_knowledge(query: str, top_k: int = 5) -> list[dict]:
embedding = await embed(query)
results = collection.query(query_embeddings=[embedding], n_results=top_k)
return [{"text": doc, "score": score} for doc, score in zip(...)]
@mcp.tool()
async def write_note(title: str, content: str) -> str:
doc_id = collection.add(documents=[content], metadatas=[{"title": title}])
return f"Note saved: {doc_id}"
Serveurs MCP communautaires à réutiliser :
- @modelcontextprotocol/server-filesystem — lecture/écriture fichier en bac à sable
- server-github — issues, PR, recherche de code
- server-brave-search — recherche web en temps réel
- server-postgres — requêtes SQL en lecture seule
- server-slack — messages de canal et notifications
Panorama de l'écosystème MCP en 2026 :
- Échelle de l'écosystème : en 2026, les serveurs MCP publics dépassent 10 000. Les étoiles GitHub combinées des dépôts modelcontextprotocol dépassent 50 000.
- Adoption éditeurs : OpenAI a annoncé le support MCP natif au T1 2026 ; Google Gemini et Microsoft Copilot ont suivi au T2. La gouvernance est passée à l'AAIF sous la Linux Foundation.
- Coût d'intégration entreprise : les enquêtes sectorielles rapportent une baisse d'environ 38–55 % du coût d'intégration des toolchains IA après standardisation sur les interfaces MCP.
Parcours d'apprentissage suggéré :
- Lisez la spec officielle et comprenez le flux de messages JSON-RPC
- Construisez Hello World avec FastMCP et déboguez dans Inspector
- Implémentez au moins trois Tools réels (fichier, HTTP, DB)
- Ajoutez Resources et Prompts pour expérimenter les trois primitives
- Basculez vers le transport HTTP et déployez en Docker sur le cloud
- Connectez Cursor et complétez un projet d'intégration base de connaissances ou GitHub
Utilisez les références publiques ci-dessous pour vérifier specs et SDK. Si les dépôts upstream changent, considérez les sources liées comme faisant autorité.
Model Context Protocol — spécification et documentation officielles
modelcontextprotocol/python-sdk — SDK Python MCP
modelcontextprotocol/typescript-sdk — SDK TypeScript MCP
modelcontextprotocol/inspector — outil de débogage MCP Inspector
Faire tourner un MCP Server sur un MacBook qui se met en veille provoque des pannes récurrentes : sessions tools/list interrompues, tokens OAuth expirés, disques pleins corrompant les bases vectorielles, et déconnexions SSE après changement de réseau. Ces problèmes affectent le dev quotidien plus que le choix du modèle. Docker sur portable hérite toujours de la veille de l'hôte. Les cold starts PaaS gratuits cassent les connexions longues. Lambda est mal adapté au SSE permanent.
Pour une toolchain MCP 7j/7, un SSH stable et une puissance Apple Silicon prévisible, migrer Cursor Agent et votre serveur custom vers du bare metal dédié est souvent le meilleur compromis. NOVAKVM propose des locations flexibles Mac Mini M4 / M4 Pro multi-régions pour Cursor MCP, dev Claude Desktop distant et bases vectorielles co-localisées. Consultez la page tarifs, commandez sur la page commande, et les questions de déploiement sur le centre d'aide.