AI Agent MCP 2026.06.16

Créer un MCP Server from scratch : construire pas à pas la capacité d'appel d'outils IA

Un grand modèle, aussi performant soit-il, ne peut pas interroger une base de données, appeler une API ou lire des fichiers par lui-même. La capacité d'appel d'outils IA détermine si un agent peut atteindre le monde réel. Le MCP (Model Context Protocol), protocole standard open source d'Anthropic, permet à Claude, Cursor et d'autres clients de découvrir et d'invoquer vos serveurs de manière unifiée. Ce guide s'adresse aux développeurs backend et IA maîtrisant Python ou TypeScript : il couvre les principes du protocole, la mise en place de l'environnement, les trois capacités Tools / Resources / Prompts, le déploiement HTTP distant, le débogage et la mise en production.

À la fin de la lecture, vous saurez répondre à trois questions : ① en quoi MCP diffère fondamentalement de Function Calling et des LangChain Tools ; ② comment enregistrer outils, ressources et modèles de prompts avec le SDK officiel ; ③ comment encapsuler une base de connaissances personnelle en MCP Server prêt pour la production et interroger Cursor : « Quelles notes ai-je prises sur MCP la semaine dernière ? »

01 Qu'est-ce que MCP ? Principes, mécanismes et comparaison

L'appel d'outils a connu trois générations : Function Calling (formats propriétaires) → Plugins (liés à la plateforme) → MCP (standard ouvert). La motivation centrale d'Anthropic : unifier via JSON-RPC la façon dont les clients IA découvrent, décrivent et invoquent des capacités externes, et mettre fin au cauchemar N modèles × M outils.

  • Problème adressé : les modèles n'accèdent pas aux outils externes ni aux données en temps réel — pas de requêtes BDD, d'appels API ou d'opérations fichiers.
  • Cas d'usage : vous voulez que Claude / GPT interroge une base, appelle une REST API, lise et écrive du Markdown local — c'est précisément ce qu'expose un MCP Server.
  • Promesse : à l'issue de cet article, vous pourrez développer et déployer un MCP Server prêt pour la production.

Architecturalement, le MCP Client (Claude Desktop, Cursor, etc.) et le MCP Server (votre code) communiquent en JSON-RPC bidirectionnel ; le serveur se connecte aux systèmes externes :

  • Tools : fonctions invocables par l'IA (recherche, calcul, requête BDD)
  • Resources : ressources lisibles par l'IA (fichiers, URL, flux de données)
  • Prompts : modèles de prompts prédéfinis avec injection de paramètres

La communication repose sur JSON-RPC 2.0. Deux modes de transport : stdio (sous-processus local, latence minimale) et HTTP + SSE / Streamable HTTP (service distant, multi-clients). Cycle de vie : poignée de main d'initialisation → négociation des capacités → requêtes/réponses → fermeture.

MCP vs OpenAI Function Calling vs LangChain Tools
Dimension MCP OpenAI Function Calling LangChain Tools
Standardisation Protocole ouvert Propriétaire éditeur Lié au framework
Transport stdio / HTTP HTTP HTTP
Multi-modèles Oui Non Partiel
Ressources / prompts Support natif Non supporté Non supporté
Écosystème Croissance rapide (10 000+ serveurs) Mature Mature

Pour aller plus loin : Pourquoi MCP devient le HTTP de l'ère IA ; spécification officielle sur modelcontextprotocol.io.

02 Environnement de développement : langage, dépendances et structure

Python (recommandé pour débuter) : SDK officiel mcp, décorateurs FastMCP concis et accessibles. TypeScript (recommandé frontend / full-stack) : SDK officiel @modelcontextprotocol/sdk. Cet article privilégie Python, avec TypeScript en contrepoint.

terminal
Environnement Python
python -m venv .venv
source .venv/bin/activate
pip install mcp

Environnement TypeScript (référence)
npm init -y
npm install @modelcontextprotocol/sdk

Structure de projet recommandée :

my-mcp-server/
my-mcp-server/
├── server.py            Point d'entrée principal
├── tools/
│   ├── __init__.py
│   ├── calculator.py
│   └── web_search.py
├── resources/
│   └── file_reader.py
├── prompts/
│   └── templates.py
├── tests/
│   └── test_tools.py
├── pyproject.toml
└── README.md

Trois outils de débogage essentiels :

  • MCP Inspector : interface officielle pour tester visuellement Tools / Resources / Prompts
  • Claude Desktop : éditer claude_desktop_config.json pour l'intégration locale
  • Configuration MCP Cursor : Settings → MCP → ajouter une commande stdio

03 Hello World : MCP Server minimal et intégration Cursor

Avec FastMCP, dix lignes suffisent pour un premier serveur fonctionnel :

server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-first-server")

@mcp.tool()
def say_hello(name: str) -> str:
    """Salue la personne indiquée"""
    return f"Hello, {name}! Voici votre premier outil MCP."

if __name__ == "__main__":
    mcp.run()

Exécution et vérification :

terminal
python server.py
Ou via MCP Inspector
npx @modelcontextprotocol/inspector python server.py

Intégration Cursor en six étapes :

  1. Confirmer le chemin Python : dans le venv, which python et noter le chemin absolu.
  2. Ouvrir les paramètres MCP Cursor : Settings → Features → MCP Servers.
  3. Ajouter un serveur stdio : command = chemin Python, args = chemin absolu de server.py.
  4. Redémarrer Cursor : pour appliquer la configuration MCP.
  5. Vérifier la liste d'outils : en mode Agent, confirmer la présence de say_hello.
  6. Déclencher un appel : demander à l'IA d'« utiliser say_hello pour saluer JEXCLOUD » et valider la réponse.

Même logique pour Claude Desktop : éditer ~/Library/Application Support/Claude/claude_desktop_config.json et enregistrer la même configuration sous mcpServers.

04 Développement Tools : types de paramètres, cinq outils pratiques et mode async

Contrat d'un outil : la signature de fonction fait office de documentation — types de paramètres, type de retour et docstring sont convertis par MCP en JSON Schema pour l'IA. Nommage en snake_case ; privilégier des erreurs structurées plutôt que des exceptions brutes.

Paramètres complexes modélisés avec Pydantic :

tools/web_search.py
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    query: str = Field(description="Mot-clé de recherche")
    max_results: int = Field(default=5, description="Nombre maximal de résultats")
    language: str = Field(default="fr", description="Langue des résultats")

@mcp.tool()
def web_search(input: SearchInput) -> list[dict]:
    """Effectue une recherche web et retourne la liste des résultats"""
    ...

Cinq outils pratiques comme checklist d'entraînement :

  • Calculatrice : évaluation sécurisée d'expressions (ast.literal_eval anti-injection)
  • Lecture/écriture fichiers : read / write limités à un répertoire autorisé
  • Requêtes HTTP : GET / POST avec timeout et retry uniformes
  • Requête base de données : SQL en lecture seule + paramétrage anti-injection
  • Outils temporels : heure courante, conversion fuseau, format ISO 8601

Outils IO-intensifs en asynchrone :

async tool
import httpx

@mcp.tool()
async def fetch_url(url: str) -> str:
    """Récupère le contenu de l'URL indiquée"""
    async with httpx.AsyncClient() as client:
        response = await client.get(url, timeout=30.0)
        return response.text

Bonnes pratiques d'erreurs : timeouts, contrôle d'accès (whitelist de chemins / clé API), retour structuré {"error": "...", "code": "..."} pour l'auto-correction de l'IA.

05 Resources : adressage URI, ressources statiques et dynamiques

Resource vs Tool : la Resource fournit des données (lecture seule), le Tool exécute des actions (écriture, effets de bord). Adressage par schéma URI : file://, http://, custom://.

resources
Ressource statique
@mcp.resource("config://app-settings")
def get_app_settings() -> str:
    return json.dumps({"version": "1.0", "env": "production"})

Ressource dynamique (paramétrée)
@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    user = db.query_user(user_id)
    return json.dumps(user)

Types de ressources couverts :

  • Texte : text/plain, application/json
  • Binaire : images, PDF (Base64 ou URI blob)
  • Streaming : logs temps réel, flux de marché (abonnement ressource)

Serveur de ressources système de fichiers : lister un répertoire → lire un fichier par chemin → optionnellement watchfiles pour détecter les changements et notifier les mises à jour.

06 Prompts : modèles réutilisables et scénarios multi-tours

Un MCP Prompt est un fragment de prompt prédéfini que le client IA peut réutiliser directement, avec injection dynamique de paramètres pour la cohérence et la maintenabilité des prompts d'équipe.

prompts/templates.py
from mcp.types import PromptMessage, TextContent

@mcp.prompt()
def code_review_prompt(language: str, code: str) -> list[PromptMessage]:
    """Modèle de prompt pour revue de code"""
    return [
        PromptMessage(
            role="user",
            content=TextContent(
                type="text",
                text=f"Veuillez examiner le code {language} suivant..."
            )
        )
    ]

Les modèles multi-tours mélangent les rôles user et assistant. Scénarios typiques : simulation d'entretien (assistant pose, user répond), assistant de débogage (assistant guide les étapes).

07 Transport HTTP : MCP Server distant et durcissement sécurité

stdio vs HTTP + SSE
Caractéristique stdio HTTP + SSE
Déploiement Processus local Serveur distant
Latence Très faible Dépend du réseau
Multi-clients Non supporté Supporté
Cas d'usage Outils locaux SaaS / partage d'équipe
server.py (HTTP)
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("remote-server", transport="streamable-http")

if __name__ == "__main__":
    mcp.run(host="0.0.0.0", port=8000)

En production, ajouter : authentification Bearer Token, middleware clé API, whitelist CORS, limitation de débit (ex. slowapi). Les serveurs distants conviennent aux requêtes BDD partagées, passerelles API internes, etc.

08 Débogage et tests : MCP Inspector, tests unitaires, erreurs courantes

Workflow MCP Inspector : lancer Inspector → connecter la commande stdio → tester tools/call dans l'UI → consulter les logs JSON-RPC → simuler timeout et refus de permission.

tests/test_tools.py
import pytest
from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client

@pytest.mark.asyncio
async def test_calculator_tool():
    server_params = StdioServerParameters(command="python", args=["server.py"])
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("calculate", {"expression": "2 + 2"})
            assert result.content[0].text == "4"
Erreurs courantes et résolution
Erreur Cause Solution
Outil absent dans l'IA Chemin de configuration incorrect Vérifier les chemins absolus command / args dans config.json
Échec sérialisation JSON Type de retour non supporté Convertir en chaîne ou dict
Timeout / déconnexion Exécution trop lente Passer en async + contrôle de timeout
Permission refusée Chemin fichier restreint Configurer une whitelist de répertoires autorisés

09 Déploiement production : Docker, cloud et observabilité

Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "server.py"]

Options de déploiement :

  • Railway / Render : déploiement en un clic, adapté aux projets personnels
  • AWS Lambda / Google Cloud Run : serverless, facturation à l'appel
  • VPS dédié : reverse proxy Nginx + TLS avec Bearer Token

Trois piliers d'observabilité : logs structurés des requêtes, métriques Prometheus des appels d'outils, alertes Sentry ; endpoint /health. Gestion de version : déclarer la version du protocole MCP, upgrades d'outils rétrocompatibles, négociation des capacités pour éviter les crashs client.

10 Projet pratique : MCP Server de base de connaissances personnelle

Besoin : permettre à l'IA de rechercher des notes Markdown locales, effectuer une recherche sémantique, créer et mettre à jour des notes.

Stack technique :

  • Base vectorielle : ChromaDB ou Qdrant (léger en local)
  • Modèle d'embedding : text-embedding-3-small (OpenAI) ou local nomic-embed-text
  • Surveillance fichiers : watchfiles pour reconstruire l'index de façon incrémentale

Modules clés :

  • Outil index_notes : scanner le répertoire, découper, embedder, écrire en base vectorielle
  • Outil semantic_search : query → top-k fragments pertinents
  • Outil write_note : créer / ajouter des fichiers Markdown
  • Ressource notes://{path} : lire le texte intégral d'une note par URI

Démonstration : dans Cursor, demander « Qu'ai-je noté sur MCP la semaine dernière ? » → l'IA appelle semantic_search → retourne les fragments pertinents et synthétise la réponse. Le chemin le plus court pour brancher une connaissance privée dans un workflow agent.

11 Écosystème MCP, parcours d'apprentissage et hébergement production

Serveurs communautaires recommandés :

  • mcp-server-filesystem : opérations système de fichiers
  • mcp-server-github : opérations sur dépôts GitHub
  • mcp-server-brave-search : recherche web
  • mcp-server-postgres : requêtes base de données
  • mcp-server-slack : messages Slack

Tendances écosystème 2026 : Cursor, Claude Desktop, VS Code, OpenAI et Google Gemini supportent ou prévoient MCP nativement ; MCP Marketplace accélère la distribution ; standards entreprise (OAuth 2.1, journaux d'audit) entrent dans la feuille de route.

Prochaines étapes : lire la spécification MCP → publier un premier serveur public → explorer MCP + orchestration d'agents → contribuer par PR à l'écosystème open source.

  • Version du protocole : première publication 2024-11-05 ; dès 2025, Streamable HTTP remplace le SSE pur comme transport distant recommandé
  • Taille de l'écosystème : plus de 10 000 serveurs MCP communautaires en 2026
  • Maintenance SDK : open source Anthropic + gouvernance Linux Foundation AAIF ; SDK Python / TypeScript officiels mis à jour chaque semaine

MCP est le protocole standard de l'outillage IA — maîtriser le développement de serveurs, c'est donner à tout LLM l'accès à vos systèmes métier. Quel outil comptez-vous encapsuler ? Partagez votre cas d'usage en commentaire.

Le coût caché d'un MCP Server en production réside dans la stabilité de l'hôte : fermer un laptop tue le sous-processus STDIO ; une connexion domestique instable interrompt le HTTP longue durée ; un VPS partagé sans sandbox macOS ni permissions TCC. Pour indexer une base de connaissances 24/7, un MCP HTTP distant ou un CI avec Cursor Agent, le Mac bare metal multi-région JEXCLOUD offre Apple Silicon dédié, IP publique fixe, livraison en 120 secondes et location mensuelle flexible — plus adapté à la production qu'un bricolage local avec reconnexions permanentes. Nœuds et tarifs : page tarifs JEXCLOUD ; questions de déploiement : centre d'aide.