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.
È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.
È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.
È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.
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.
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.
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.
{
"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.
| Dimension | OpenAI Function Calling | LangChain Tools | MCP |
|---|---|---|---|
| Portée | API OpenAI uniquement | Frameworks agents Python | Tout Host MCP (Cursor, Claude, ChatGPT, VS Code) |
| Découverte | Statique : liste codée en dur dans l'appel API | Statique : outils enregistrés en Python au démarrage | Dynamique : tools/list à l'init de session |
| Auto-description | JSON Schema dans le payload API | Schémas Pydantic / dict en code | JSON Schema renvoyé par le Server ; idem pour Resources et Prompts |
| Accès données | Pas de couche lecture seule standard | Retrievers custom par framework | Resources avec schéma URI (file://, db://) |
| Modèles réutilisables | System prompts uniquement | Objets PromptTemplate | Capacité Prompts avec schémas d'arguments |
| Transport | HTTPS vers OpenAI | Appels Python in-process | Sous-processus STDIO ou HTTP streamable distant |
| Portabilité | Verrouillé éditeur | Verrouillé framework | Écrire le Server une fois ; tout client se connecte |
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 :
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.
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.
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.
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.
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.
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 :
Bearer tokens : validez Authorization: Bearer <token> sur chaque requête. Rotation via variables d'environnement, jamais en dur dans le code.
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.
CORS : restreignez Access-Control-Allow-Origin aux origines Host connues. Le wildcard * sur des endpoints MCP production est une misconfiguration fréquente.
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.
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ôme | Cause probable | Correctif |
|---|---|---|
| Server absent dans Cursor | Chemin config ou commande incorrecte | Vérifiez command/args dans mcp.json ; contrôlez que le sous-processus démarre sans erreur d'import |
| tools/list renvoie vide | Décorateurs non enregistrés avant run() | Importez les modules outils dans le point d'entrée server.py |
| Connexion HTTP refusée | Port incorrect ou transport incompatible | Alignez le transport client sur le mode serveur (STDIO vs streamable-http) |
| Erreur CORS dans client navigateur | En-têtes manquants ou trop stricts | Ajoutez les origines autorisées ; activez credentials uniquement si nécessaire |
| Timeout appel outil | Blocage sync dans contexte async | Utilisez des tools async def ou asyncio.to_thread pour l'I/O |
| JSON Schema invalide rejeté | Modèle Pydantic sans descriptions Field | Ajoutez 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 :
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.
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.
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.
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.
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.
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.
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 :
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.
AWS Lambda : fonctionne pour des appels d'outils stateless uniquement — évitez pour des sessions SSE persistantes. Utilisez API Gateway + handlers éphémères.
Google Cloud Run : scale les serveurs HTTP streamable ; fixez min instances à 1 pour garder les sessions chaudes.
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 :
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.
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.
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).
~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.
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.