Créer un MCP Server de zéro :
guide complet pour développeurs

Protocole · Tools · Resources · Prompts · transport HTTP · déploiement production

Créer un MCP Server de zéro guide développeur
Public visé : développeurs qui savent qu'un LLM peut appeler des outils, mais butent sur le câblage manuel de chaque modèle à chaque API. Ce que vous obtenez : un parcours complet de zéro à un MCP Server prêt pour la production — fondamentaux du protocole, Hello World FastMCP, cinq outils réels avec schémas Pydantic, Resources et Prompts, transport HTTP streamable avec auth, déploiement Docker et capstone base de connaissances ChromaDB. Structure : évolution et architecture (s1–s2), implémentation hands-on (s3), HTTP/debug/runbook en six étapes (s4), hébergement production et données écosystème 2026 (s5).
01

Pourquoi MCP existe : Function Calling, Plugins et le mur d'intégration

Les LLM raisonnent bien mais exécutent mal. La première réponse fut le Function Calling d'OpenAI (juin 2023) : définir des schémas JSON, laisser le modèle émettre des appels structurés, votre code les exécute. Ça marchait — mais uniquement dans l'API OpenAI. Chaque autre modèle exigeait un adaptateur séparé.

Les Plugins ChatGPT (mars 2023) ont tenté un modèle marketplace : chaque plugin était un wrapper REST sur mesure avec son propre manifeste. La découverte était centralisée dans la boutique OpenAI, pas dynamique au runtime. Quand Anthropic a livré Tool Use et que LangChain a popularisé les frameworks agents, l'industrie avait trois schémas d'outils incompatibles et aucune couche serveur portable.

01

Ère Function Calling : schémas par éditeur. GPT, Claude et Gemini attendent chacun des formes de messages différentes. Changer de modèle → réécrire le pont outils.

02

Ère Plugins : découverte centralisée dans une boutique, pas dans votre runtime agent. Pas de standard pour Resources ou Prompts — seulement des endpoints appelables.

03

Ère frameworks : LangChain Tools, outils CrewAI et hooks spécifiques à chaque IDE définissent leurs propres objets outils. Les définitions ne voyagent pas entre Cursor, VS Code et Claude Desktop.

04

Coût N×M : N clients IA × M backends = N×M intégrations. Les équipes CRM enterprise maintiennent des couches adaptateurs parallèles pour chaque éditeur LLM.

05

Réponse MCP (nov. 2024) : Anthropic open-source un protocole unique — JSON-RPC 2.0 sur STDIO ou HTTP — où les Servers s'auto-décrivent via Tools, Resources et Prompts. Écrivez une fois ; Cursor, Claude Desktop, ChatGPT, Gemini et VS Code se connectent sans réécriture.

La logique de conception d'Anthropic rappelle l'USB-C : standardiser le port, pas chaque câble. MCP ne remplace pas les API REST — il les enveloppe derrière une couche uniforme de découverte et d'invocation pour que les clients IA cessent de se soucier du vendor ou du framework de l'autre côté. Au T2 2026, la gouvernance est passée à la Linux Foundation AAIF ; OpenAI, Google et Microsoft livrent tous un support client MCP natif.

Function Calling a résolu « comment un modèle appelle une fonction ? » MCP résout « comment n'importe quel client IA découvre et invoque n'importe quel serveur d'outils ? » — la question que toute stack agent affronte en 2026.

02

Architecture MCP : Client/Server, trois capacités et cycle de vie transport

MCP repose sur JSON-RPC 2.0 avec messagerie bidirectionnelle. Un Host (Cursor, Claude Desktop) embarque un ou plusieurs MCP Clients. Chaque Client maintient une session 1:1 avec un MCP Server qui fait le pont vers les systèmes réels.

Les Servers exposent trois types de capacités : Tools (actions exécutables avec effets de bord), Resources (données en lecture seule identifiées par URI) et Prompts (modèles de texte réutilisables que le client peut pré-remplir). Les méthodes RPC centrales incluent tools/list, tools/call, resources/list, resources/read, prompts/list et prompts/get.

JSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "query_database",
    "arguments": { "sql": "SELECT id, email FROM users LIMIT 10" }
  },
  "id": 42
}

Transport STDIO : le Host lance le Server en sous-processus ; les messages circulent sur stdin/stdout. Zéro dépendance réseau, isolation process forte, idéal pour le dev local. Cycle de vie : spawn → handshake initialize → négociation des capacités → session persistante → sortie du sous-processus à la déconnexion.

HTTP + SSE / streamable-http : le Server tourne comme service HTTP longue durée. Le Client ouvre un flux SSE pour les événements server-push ; les appels d'outils passent en POST. Permet déploiement distant, serveurs partagés en équipe, scaling horizontal — mais exige affinité de session pour SSE et auth correcte en edge. La spec 2026 ajoute streamable-http comme transport distant recommandé, remplaçant les patterns SSE-only hérités.

DimensionOpenAI Function CallingLangChain ToolsMCP
PortéeAPI OpenAI uniquementFrameworks agents PythonTout Host MCP (Cursor, Claude, ChatGPT, VS Code)
DécouverteStatique : liste codée en dur dans l'appel APIStatique : outils enregistrés en Python au démarrageDynamique : tools/list à l'init de session
Auto-descriptionJSON Schema dans le payload APISchémas Pydantic / dict en codeJSON Schema renvoyé par le Server ; idem pour Resources et Prompts
Accès donnéesPas de couche lecture seule standardRetrievers custom par frameworkResources avec schéma URI (file://, db://)
Modèles réutilisablesSystem prompts uniquementObjets PromptTemplateCapacité Prompts avec schémas d'arguments
TransportHTTPS vers OpenAIAppels Python in-processSous-processus STDIO ou HTTP streamable distant
PortabilitéVerrouillé éditeurVerrouillé frameworkÉcrire le Server une fois ; tout client se connecte
03

Setup dev et implémentation : FastMCP, Tools, Resources et Prompts

Choisissez votre stack SDK : Python avec mcp + FastMCP pour itérer le plus vite, ou TypeScript avec @modelcontextprotocol/sdk pour des serveurs HTTP natifs Node. Arborescence projet recommandée :

structure projet
my-mcp-server/
  pyproject.toml
  src/
    server.py          # entrée FastMCP
    tools/             # modules outils
    resources/         # handlers resources
    prompts/           # modèles prompts
  tests/
    test_tools.py
  Dockerfile

Installation : pip install mcp ou npm install @modelcontextprotocol/sdk. Debug avec MCP Inspector (npx @modelcontextprotocol/inspector) — se connecte aux endpoints STDIO ou HTTP et affiche le tools/list en direct. Branchez dans Cursor via Paramètres → MCP → ajouter config serveur ; Claude Desktop via claude_desktop_config.json.

Python · FastMCP Hello World
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-mcp")

@mcp.tool()
def greet(name: str) -> str:
    return f"Hello, {name}!"

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

Tools avec entrée Pydantic : FastMCP dérive le JSON Schema depuis les type hints et modèles Pydantic automatiquement. Ci-dessous : cinq outils pratiques — calculateur, I/O fichier, requête HTTP, requête DB et horodatage — avec support async et retours d'erreur structurés.

Python · cinq outils
import asyncio
import httpx
from datetime import datetime, timezone
from pathlib import Path
from pydantic import BaseModel, Field
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("utility-server")

class CalcInput(BaseModel):
    expression: str = Field(description="Expression math ex. 2 + 3 * 4")

@mcp.tool()
def calculate(input: CalcInput) -> str:
    try:
        allowed = set("0123456789+-*/(). ")
        if not all(c in allowed for c in input.expression):
            return "Error: invalid characters in expression"
        return str(eval(input.expression, {"__builtins__": {}}, {}))
    except Exception as e:
        return f"Error: {e}"

@mcp.tool()
def read_file(path: str) -> str:
    try:
        target = Path(path).resolve()
        if not target.is_file():
            return f"Error: {path} is not a file"
        return target.read_text(encoding="utf-8", errors="replace")[:50000]
    except Exception as e:
        return f"Error: {e}"

@mcp.tool()
async def http_get(url: str) -> str:
    try:
        async with httpx.AsyncClient(timeout=15.0) as client:
            resp = await client.get(url)
            return resp.text[:10000]
    except Exception as e:
        return f"Error: {e}"

@mcp.tool()
async def db_query(sql: str) -> str:
  try:
    import aiosqlite
    async with aiosqlite.connect("app.db") as db:
      cursor = await db.execute(sql)
      rows = await cursor.fetchall()
      return str(rows[:100])
  except Exception as e:
    return f"Error: {e}"

@mcp.tool()
def current_time(tz: str = "UTC") -> str:
    return datetime.now(timezone.utc).isoformat()

Resources : les URI statiques mappent vers des fichiers fixes ; les URI dynamiques acceptent des paramètres. Un serveur de resources filesystem expose la doc projet que l'agent peut lire sans effets de bord d'outil.

Python · resources filesystem
from mcp.server.fastmcp import FastMCP
from pathlib import Path

mcp = FastMCP("fs-resources")
DOCS = Path("./docs")

@mcp.resource("docs://index")
def docs_index() -> str:
    files = [f.name for f in DOCS.glob("*.md")]
    return "\n".join(files)

@mcp.resource("docs://{filename}")
def read_doc(filename: str) -> str:
    path = DOCS / filename
    if not path.exists():
        return f"Error: {filename} not found"
    return path.read_text(encoding="utf-8")

Prompts : modèles réutilisables avec emplacements d'arguments. Un prompt de revue de code pré-remplit le contexte pour que l'agent suive la checklist de votre équipe.

Python · prompt revue de code
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("review-prompts")

@mcp.prompt()
def code_review(file_path: str, language: str) -> str:
    return f"""Review {file_path} ({language}) for:
1. Security vulnerabilities (injection, auth bypass)
2. Performance bottlenecks
3. Error handling gaps
4. Test coverage holes
Provide severity-rated findings with fix suggestions."""

Snippet config Cursor : ajoutez dans .cursor/mcp.json{"mcpServers": {"utility": {"command": "python", "args": ["src/server.py"]}}}. Claude Desktop utilise la même forme dans claude_desktop_config.json.

04

Transport HTTP, débogage et runbook MCP Server en six étapes

Le transport HTTP streamable est le défaut 2026 pour les MCP Servers distants. Lancez FastMCP avec mcp.run(transport="streamable-http") ou utilisez StreamableHTTPServerTransport du SDK TypeScript. Couchez la sécurité en edge :

01

Bearer tokens : validez Authorization: Bearer <token> sur chaque requête. Rotation via variables d'environnement, jamais en dur dans le code.

02

Clés API : acceptez l'en-tête X-API-Key pour des configs client plus simples. Mappez les clés vers des limites de débit par tenant.

03

CORS : restreignez Access-Control-Allow-Origin aux origines Host connues. Le wildcard * sur des endpoints MCP production est une misconfiguration fréquente.

04

Rate limiting : plafonnez les requêtes par clé au reverse proxy (nginx, Cloudflare) ou en middleware applicatif. Les appels d'outils MCP peuvent déclencher des API downstream coûteuses.

Workflow de débogage : MCP Inspector d'abord, puis logs client, puis tests unitaires. Inspector affiche le JSON-RPC brut, les erreurs de validation de schéma et le timing par appel.

Python · test unitaire pytest
import pytest
from server import calculate, CalcInput

def test_calculate_valid():
    result = calculate(CalcInput(expression="2 + 3"))
    assert result == "5"

def test_calculate_invalid_chars():
    result = calculate(CalcInput(expression="import os"))
    assert result.startswith("Error:")
SymptômeCause probableCorrectif
Server absent dans CursorChemin config ou commande incorrecteVérifiez command/args dans mcp.json ; contrôlez que le sous-processus démarre sans erreur d'import
tools/list renvoie videDécorateurs non enregistrés avant run()Importez les modules outils dans le point d'entrée server.py
Connexion HTTP refuséePort incorrect ou transport incompatibleAlignez le transport client sur le mode serveur (STDIO vs streamable-http)
Erreur CORS dans client navigateurEn-têtes manquants ou trop strictsAjoutez les origines autorisées ; activez credentials uniquement si nécessaire
Timeout appel outilBlocage sync dans contexte asyncUtilisez des tools async def ou asyncio.to_thread pour l'I/O
JSON Schema invalide rejetéModèle Pydantic sans descriptions FieldAjoutez Field(description=...) pour des paramètres lisibles par l'agent

Runbook en six étapes de l'évaluation au MCP Server prêt pour la production :

01

Cartographier les intégrations : listez les systèmes externes (DB, Git, Slack, API internes). Comptez les adaptateurs actuels par modèle et estimez le coût de réécriture en cas de changement d'éditeur.

02

Choisir SDK et transport : FastMCP Python pour prototypage STDIO ; ajoutez streamable-http quand l'équipe a besoin d'accès distant. TypeScript si votre stack est Node.

03

Implémenter les capacités : commencez avec 2–3 Tools, un schéma URI Resource, un modèle Prompt. Validez les schémas dans MCP Inspector avant de brancher les clients.

04

Brancher les clients : ajoutez le serveur dans mcp.json Cursor et la config Claude Desktop. Confirmez tools/list au démarrage de session — pas de tableaux d'outils codés en dur dans les prompts.

05

Tester et durcir : tests unitaires par outil, tests d'intégration via Inspector, chaînes d'erreur structurées plutôt que tracebacks bruts vers le LLM.

06

Déployer sur hôte 7×24 : dockerisez, poussez vers Railway/Render/Cloud Run ou un VPS dédié. Pour inférence Apple Silicon et CI Xcode sur le même nœud, préférez un Mac Mini cloud plutôt qu'un VPS Linux.

05

Déploiement production, capstone, écosystème et chiffres clés

Chemins production : packagez avec Docker (base python:3.12-slim, utilisateur non-root, health check sur le port HTTP). Options plateforme :

A

Railway / Render : poussez le conteneur, définissez les variables d'environnement pour les clés API, exposez le port HTTP. Adapté aux serveurs dev/staging partagés en équipe.

B

AWS Lambda : fonctionne pour des appels d'outils stateless uniquement — évitez pour des sessions SSE persistantes. Utilisez API Gateway + handlers éphémères.

C

Google Cloud Run : scale les serveurs HTTP streamable ; fixez min instances à 1 pour garder les sessions chaudes.

D

VPS / bare metal : contrôle total pour agents longue durée, embeddings locaux et stacks multi-serveurs sur un seul hôte.

Monitoring : exportez latence requête et compteurs d'appels d'outils vers Prometheus ; envoyez les exceptions à Sentry avec tags nom de méthode MCP. Épinglez les versions SDK dans pyproject.toml / package.json et taguez les images Docker par release — les révisions spec MCP en 2026 apportent encore des changements breaking sur le transport.

Capstone : MCP base de connaissances personnelle. Combinez store vectoriel ChromaDB, modèle d'embedding (Ollama local ou API) et outil de recherche sémantique :

Python · outil recherche ChromaDB
import chromadb
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("knowledge-base")
client = chromadb.PersistentClient(path="./chroma_data")
collection = client.get_or_create_collection("notes")

@mcp.tool()
def semantic_search(query: str, n: int = 5) -> str:
    results = collection.query(query_texts=[query], n_results=n)
    docs = results.get("documents", [[]])[0]
    return "\n---\n".join(docs) if docs else "No matches found."

@mcp.tool()
def ingest_note(text: str, source: str) -> str:
    collection.add(documents=[text], metadatas=[{"source": source}], ids=[source])
    return f"Indexed: {source}"

Serveurs écosystème 2026 à étudier : mcp-server-filesystem (référence officielle), GitHub MCP (ops repo/PR/issue), Brave Search MCP (récupération web), Postgres MCP (SQL avec introspection schéma), Slack MCP (messagerie canal). Tendances S2 2026 : auth OAuth 2.1 standardisée, registres serveurs unifiés, marketplaces MCP multi-tenant hébergées, orchestration Agent-to-Agent (A2A) au-dessus de la couche outils MCP.

A

10 000+ serveurs communautaires : le nombre de MCP servers a dépassé dix mille mi-2026 — chaque nouveau serveur atteint instantanément tout client compatible.

B

Baisse coût intégration 38–55 % : les équipes enterprise rapportent 38–55 % de dépenses d'intégration IA en moins après consolidation des adaptateurs derrière des MCP Servers (moyenne enquêtes industrie 2025–2026).

C

~1 000 serveurs exposés sans auth : des scans sécurité début 2026 ont trouvé environ mille endpoints MCP sur Internet public sans authentification — ne déployez jamais des Servers production sans Bearer tokens, clés API et isolation réseau.

Attention : un VPS Linux ne peut pas exécuter des builds Xcode ni des modèles d'embedding locaux optimisés Apple Silicon. Les sessions STDIO sur portable meurent à la veille. AWS Lambda ne peut pas maintenir des sessions MCP SSE persistantes. Chaque raccourci sacrifie quelque chose dont les agents production ont besoin.

Pour les équipes qui font tourner des MCP Servers aux côtés d'agents Cursor, ingestion ChromaDB et CI iOS sur un nœud always-on, la location Mac Mini cloud MESHLAUNCH est en général le meilleur hôte production : Apple Silicon dédié, pas de déconnexion veille, facturation jour/semaine/mois flexible, et un domicile stable où les définitions d'outils deviennent des actifs d'équipe portables au lieu de configs laptop par développeur. Consultez les tarifs pour les specs nœud ; questions réseau et accès dans le centre d'aide.

FAQ

FastMCP Python est le plus rapide pour prototyper : outils par décorateurs, JSON Schema automatique depuis les type hints, lancement STDIO en une ligne. Le SDK TypeScript @modelcontextprotocol/sdk convient aux équipes Node.js ou aux serveurs HTTP streamable sur Express. Les deux sont des SDK officiels — choisissez le langage que votre équipe livre en production. Specs nœud cloud sur la page tarifs.

Oui. Les serveurs STDIO tournent en sous-processus sur tout hôte macOS. Les serveurs HTTP streamable exigent un processus persistant et un réseau stable — un Mac Mini cloud bare metal offre Apple Silicon pour l'inférence d'embeddings locale, CI Xcode sur le même nœud, et aucune veille de portable qui tue les sessions MCP stateful.

Lancez MCP Inspector contre votre endpoint serveur, vérifiez que tools/list renvoie les schémas attendus, puis consultez les logs MCP de Cursor. Causes fréquentes : mode transport incompatible, JSON Schema invalide, crash du sous-processus à l'import, ou CORS bloquant les serveurs HTTP. Tunnel SSH et configuration des ports dans le centre d'aide.