MCP : le protocole qui permet à Claude de piloter votre application via des prompts

API Claude LLM MCP Python
MCP : le protocole qui permet à Claude de piloter votre application via des prompts

C'est parti d'un truc con. J'intégrais une API REST sur knowledge.arnaudallouche.fr — gestion des articles, catégories, tags, médias — et à mi-chemin je me suis demandé : est-ce que Claude pourrait gérer ce site directement depuis une conversation ? Sans ouvrir l'admin Django. Sans rédiger des requêtes cURL à la main. Genre, je lui dis "crée-moi un article sur Ansible" et c'est fait.

La réponse, c'est oui. Et le protocole qui rend ça possible s'appelle MCP.

Deux semaines plus tard, je pilote mon site entier via des prompts. Création d'articles, optimisation des images, audit des meta descriptions manquantes — tout ça depuis une conversation avec Claude. Je vous explique comment ça marche vraiment, avec le code que j'utilise en production et les erreurs dans lesquelles je suis tombé.

MCP, c'est quoi concrètement

Avant MCP, si vous vouliez qu'un LLM interagisse avec une application externe, vous aviez deux options. Soit vous colliez les données dans le prompt — ce qui tient sur deux pages au mieux — soit vous implémentiez du function calling propritaire, avec une interface différente pour chaque provider. Résultat : des intégrations qui ne marchent que pour un outil, dans un contexte précis, et qu'il faut réecrire pour chaque nouveau projet.

MCP (Model Context Protocol) c'est un standard ouvert développé par Anthropic. L'idée : définir un protocole commun pour que n'importe quel LLM puisse découvrir et utiliser les capacités d'une application externe. Votre serveur MCP expose des outils. Claude les découvre au démarrage de la session. Et à partir de là, il peut les appeler comme s'il les avait toujours eus.

Ce que j'ai mis du temps à vraiment comprendre, c'est la différence avec le function calling classique. En function calling, vous définissez les fonctions disponibles dans votre prompt, côté application. C'est votre code qui orchestre tout. MCP inverse le modèle : c'est un processus séparé, indépendant, qui tourne en dehors de votre application principale. Et n'importe quel client compatible peut l'utiliser — Claude Code, Claude Desktop, et bientôt d'autres. Vous montez le serveur une fois, tous les clients en profitent.

Ce que contient un serveur MCP

Un serveur MCP, dans sa forme la plus basique, c'est un script Python qui tourne sur votre machine. Le transport par défaut est stdio — Claude Code démarre votre script en subprocess et communique via stdin/stdout avec des messages JSON. Volontairement simple, volontairement portable.

Voilà ce que ça donne avec la librairie mcp d'Anthropic :

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("mon-serveur")

@mcp.tool()
async def lire_article(article_id: int) -> str:
    """Récupère le contenu complet d'un article par son ID"""
    # votre logique ici
    return "contenu de l'article"

@mcp.tool()
async def creer_article(titre: str, contenu: str) -> str:
    """Crée un nouvel article en brouillon"""
    # votre logique ici
    return "Article créé avec l'ID 42"

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

Chaque fonction décorée avec @mcp.tool() devient un outil que Claude peut appeler. Mais la partie qui fait vraiment la différence, c'est la docstring. C'est elle que Claude lit pour décider quand et comment utiliser l'outil. J'ai passé deux fois plus de temps à soigner ces descriptions qu'à écrire le code des fonctions elles-mêmes — et franchement, c'est là que se joue 80% de la qualité du résultat.

Le protocole définit trois types de primitives : les Tools (fonctions que le modèle peut appeler), les Resources (données qu'il peut lire) et les Prompts (templates réutilisables). Pour piloter une API, les Tools suffisent largement. Les deux autres deviennent utiles pour des architectures plus complexes que je n'ai pas encore eu besoin d'explorer.

Mettre MCP devant une API REST existante

Mon cas d'usage : j'avais déjà une API Django avec des endpoints pour créer, modifier, supprimer des articles. Le serveur MCP est juste une couche de translation entre les appels de Claude et les requêtes HTTP. Aucune logique métier — ça reste dans l'API. Voilà ce que ça donne :

import os, json
import httpx
from mcp.server.fastmcp import FastMCP

API_URL = os.environ.get("API_URL", "https://knowledge.arnaudallouche.fr")
API_TOKEN = os.environ.get("API_TOKEN", "")

mcp = FastMCP("knowledge-api")

def _headers():
    return {"Authorization": f"Token {API_TOKEN}", "Content-Type": "application/json"}

@mcp.tool()
async def creer_article(
    titre: str,
    contenu: str,
    statut: str = "draft",
    categorie_id: int = None,
    tag_ids: list[int] = None
) -> str:
    """
    Crée un nouvel article sur le site.
    statut : 'draft' (brouillon) ou 'published' (publié immédiatement).
    Toujours récupérer les IDs via list_categories() et list_tags() avant d'appeler cet outil.
    """
    payload = {"title": titre, "content": contenu, "status": statut}
    if categorie_id:
        payload["category"] = categorie_id
    if tag_ids:
        payload["tags"] = tag_ids
    async with httpx.AsyncClient() as c:
        r = await c.post(f"{API_URL}/api/articles/", json=payload, headers=_headers())
        return json.dumps(r.json(), indent=2, ensure_ascii=False)

Ce que j'aurais voulu qu'on me dise au départ : ne mettez jamais le token en dur dans le code. Passez-le via une variable d'environnement. Si votre serveur MCP finit sur GitHub, vous n'exposez pas vos credentials par accident. Même réflexe que pour un fichier .env. Ça semble évident, mais quand on est dans le flow de dev à 23h, ce genre de détail saute facilement.

L'autre chose importante : l'API reste accessible et utilisable indépendamment du MCP. Le serveur MCP n'est pas un proxy obligatoire — c'est juste un client parmi d'autres. Si vous cassez le serveur MCP, votre API continue de fonctionner normalement. Cette séparation m'a déjà sauvé deux fois.

Ce qui se passe vraiment quand Claude utilise les outils

Au démarrage de la session, Claude Code liste les outils disponibles. À partir de là, il les intègre naturellement dans ses réponses — pas besoin de syntaxe particulière ni de prompt spécial. Vous parlez normalement, il décide lui-même quels outils appeler et dans quel ordre.

Exemple concret : je lui dis "crée-moi un article sur les bonnes pratiques Docker, catégorie Développement, avec les tags Python et DevOps". Ce qui se passe :

  1. Il appelle list_categories() pour récupérer l'ID de "Développement"
  2. Il appelle list_tags() pour trouver les IDs de "Python" et "DevOps"
  3. Il rédige le contenu en HTML
  4. Il appelle create_article() avec tout ça assemblé

Aucune ligne de code supplémentaire de ma part. Une instruction, une cascade d'appels API coordonnés. C'est là que le truc devient vraiment intéressant : Claude gère le raisonnement et l'orchestration, le serveur MCP gère l'exécution. Vous n'écrivez plus de scripts d'automatisation — vous décrivez ce que vous voulez.

J'ai testé un scénario plus complexe : "optimise toutes les images à la une qui font plus de 100 Ko". Claude a listé les articles, vérifié le poids de chaque image, téléchargé les plus lourdes, les a recompressées avec Pillow, et les a réuploadées via l'API — tout en me tenant au courant des gains à chaque étape. 705 Ko pour l'image principale de ce site, ramenée à 67 Ko. Sans que j'écrive une seule ligne de script.

La configuration côté Claude Code

C'est probablement la partie la plus simple. Un fichier mcp.json à la racine du projet :

{
  "mcpServers": {
    "knowledge-api": {
      "command": "python",
      "args": ["mcp_server.py"],
      "env": {
        "API_URL": "https://knowledge.arnaudallouche.fr",
        "API_TOKEN": "votre_token_ici"
      }
    }
  }
}

Ou via CLI :

claude mcp add knowledge-api \
  --command python \
  --args "mcp_server.py" \
  --env API_URL=https://knowledge.arnaudallouche.fr \
  --env API_TOKEN=votre_token_ici

Claude Code lance le serveur automatiquement au démarrage de la session. Pas de redémarrage à gérer, pas de port à ouvrir. Ça marche ou ça plante au démarrage — dans ce cas le message d'erreur est généralement assez clair pour comprendre ce qui cloche.

Un truc qui m'a pris du temps à comprendre : le serveur MCP tourne sur votre machine locale, pas sur le serveur distant. C'est lui qui fait les appels HTTP vers votre API. Donc si votre API est accessible depuis Internet et que votre machine a une connexion, ça marche. Pas besoin d'exposer le serveur MCP lui-même.

Les cas d'usage où ça change vraiment quelque chose

Après quelques semaines d'utilisation quotidienne, voilà ce qui m'a vraiment fait gagner du temps — pas la liste idéale, juste ce que j'ai réellement utilisé.

La gestion de contenu sans ouvrir d'interface. Dicter une instruction à Claude plutôt que de naviguer dans les menus d'un CMS, ça prend 30 secondes contre 5 minutes. Sur un site avec beaucoup de contenu, ça s'accumule. Mais surtout, ça supprime la friction mentale — je reste dans mon flux de travail sans changer de contexte.

Les audits en masse. "Liste tous les articles sans meta description et génère-en une pour chacun." Ce type de tâche qui prendrait des heures en manuel devient triviale. Claude parcourt les données, prend les décisions de rédaction, exécute les modifications. J'ai fait ça sur mes 13 articles en une seule commande.

Les tâches que je repoussais. Il y a des petites choses qu'on ne fait jamais parce que ça ne vaut pas une après-midi de dev mais que personne ne va faire à la main non plus. Optimiser 14 images, vérifier la cohérence des tags, compléter les meta keywords manquants. Avec MCP, ces tâches passent en quelques minutes.

Les limites à ne pas ignorer

Je serais malhonnête si je présentais ça comme parfait. Il y a des vrais problèmes.

Les LLMs inventent des IDs. J'ai vu Claude passer un category_id de 99 alors que ma catégorie avait l'ID 7 — parce qu'il devinait plutôt que de l'avoir récupéré explicitement. La solution : précisez dans les docstrings que les IDs doivent être récupérés via les outils de liste. Et retournez des erreurs explicites côté API quand un ID n'existe pas. Ça m'a pris deux ou trois ratés avant de comprendre le pattern.

La fenêtre de contexte se remplit vite. Si votre API retourne des gros objets — articles avec contenu HTML complet, réponses avec des centaines de résultats — vous saturez rapidement le contexte. La bonne pratique : un outil list_articles qui retourne titre + ID + statut, et un get_article séparé pour le détail. Ça paraît évident a posteriori, mais je ne l'avais pas pensé au début.

La latence s'accumule sur les workflows longs. Chaque appel d'outil, c'est un aller-retour réseau plus le temps de traitement du modèle. Un workflow avec dix étapes séquentielles peut facilement prendre une minute. C'est bien pour des tâches de fond, beaucoup moins pour de l'interactif temps réel.

La sécurité mérite réflexion. Donner à un LLM la capacité de modifier des données en production, c'est s'exposer aux erreurs de raisonnement du modèle. Je limite les opérations destructives (suppression, publication) à des outils explicitement nommés, et je travaille généralement en brouillon avant de publier. Pour des applications critiques, des modes "dry-run" et des confirmations explicites sont vraiment nécessaires.

MCP vs function calling : la vraie différence

La confusion entre les deux revient souvent, donc je la clarifie.

En function calling classique, les fonctions sont définies dans le prompt à chaque appel API. Votre application orchestre tout. C'est adapté pour des intégrations simples qui tournent dans un seul process. C'est ce que font la plupart des applications LLM aujourd'hui.

MCP résout un problème différent : la réutilisabilité entre clients. Votre serveur MCP fonctionne avec Claude Code, Claude Desktop, et n'importe quelle autre app compatible — sans toucher au code. C'est un standard, comme REST pour les APIs ou OAuth pour l'authentification. La valeur vient de la standardisation, pas de la technologie en elle-même.

Concrètement, si vous montez quelque chose pour un usage personnel ou une équipe interne, function calling peut suffire. Si vous voulez que votre intégration soit utilisable depuis plusieurs surfaces sans maintenance, MCP est le bon choix.

Ce que ça ouvre comme perspectives

Ce que je trouve vraiment intéressant dans MCP, c'est pas tant la gestion de contenu — c'est ce que ça dit sur la façon dont on va construire des applications dans les prochaines années.

Aujourd'hui, pour piloter une application complexe, vous construisez une interface : des écrans, des formulaires, des menus. Ça prend du temps, ça coûte cher, et ça reste rigide face à des besoins qui évoluent. Avec MCP, vous exposez vos opérations via des outils, et l'interface devient une conversation. "Applique une remise de 20% sur les produits de la catégorie Hiver avec un stock supérieur à 50 unités" — une règle métier complexe décrite en langage naturel, décomposée et exécutée par un agent.

On n'est pas encore là pour des opérations critiques sans supervision humaine. Les modèles font encore des erreurs de raisonnement sur des workflows complexes, les garde-fous manquent dans beaucoup de domaines. Mais les primitives existent aujourd'hui. Et MCP est l'infrastructure sur laquelle ces agents seront construits.

Pour se lancer

Si vous avez une API REST qui tourne, la mettre derrière un serveur MCP c'est quelques heures de travail. La librairie Python est bien documentée, le pattern est simple. Mon conseil pratique : commencez avec 3 ou 4 outils de lecture seulement. Testez le comportement du modèle, comprenez comment il interprète vos descriptions, voyez où il déraille. Ajoutez les opérations d'écriture progressivement, quand vous faites confiance au workflow.

Traitez vos outils comme une API publique bien conçue : noms clairs, descriptions précises, erreurs explicites. Le modèle est votre utilisateur. Il lit les descriptions pour décider quoi appeler, il réagit aux messages d'erreur pour corriger sa trajectoire. C'est exactement le même travail que de documenter une API pour des développeurs humains — et ça a exactement le même impact.

MCP est disponible aujourd'hui dans Claude Code et Claude Desktop. L'écosystème grossit vite — GitHub, Postgres, Slack, Figma ont déjà leurs serveurs. Si votre application manipule des données, il y a probablement un cas d'usage qui vaut la peine d'être exploré.

Retour aux articles Intelligence Artificielle