Accueil / Articles / Notes pratiques : Qu’est-ce que MCP ? Créer un serveur MCP personnalisé en Python

Notes pratiques : Qu’est-ce que MCP ? Créer un serveur MCP personnalisé en Python

Guide pratique pas à pas : Qu’est-ce que MCP ? Créer un serveur MCP personnalisé en Python : contrats, vérifications et emplacements de code prêts à l’emploi pour les équipes utilisant ce modèle.

2052 mots

Utilisez ceci comme une version révisée destinée aux opérateurs des idées présentées dans « Qu’est-ce que MCP ? Créez un serveur MCP personnalisé en Python » : étapes claires, emplacements de code ordonnés et notes de récupération permettant de continuer en cas de transfert. L’étape « Aperçu » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le projet passe de la démonstration aux environnements partagés.

MCP, en 90 secondes

Pour l’étape MCP en 90 secondes, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Séparez la construction du client du cycle de messages afin que les fournisseurs puissent être remplacés sans avoir à réécrire la machine à états de la conversation.

Pourquoi chaque intégration d’IA coûtait autrefois trois fois plus cher

Pour chaque étape d’intégration de l’IA, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure. Séparez la construction du client de la boucle de messages afin que les fournisseurs puissent être remplacés sans avoir à réécrire la machine à états de la conversation.

Création d’un outil Standup dans un seul fichier

Pour l’étape « Construction d’un aide pour les réunions Standup », définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Séparez la construction du client du cycle de messages afin que les fournisseurs puissent être remplacés sans avoir à réécrire la machine à états de la conversation. Pour l’étape « Construction d’un aide pour les réunions Standup », définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût en tokens ou requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût évite des factures inattendues lorsque le processus passe de la démonstration à un environnement partagé.

pip install fastmcp
# standup_server.py
import subprocess
from typing import TypedDict

from fastmcp import FastMCP

mcp = FastMCP("standup-helper")


class StandupSummary(TypedDict):
    branch: str
    since: str
    commit_count: int
    commits: list[str]


@mcp.tool()
def summarize_standup(
    branch: str = "main",
    since: str = "yesterday",
) -> StandupSummary:
    """Summarize recent git activity for a standup.

    Reads the local git log on the given branch since the
    given time window. Returns commit count and one-line
    subjects for each commit. Used by AI clients via MCP.
    """
    try:
        result = subprocess.run(
            [
                "git", "log",
                f"--since={since}",
                "--pretty=format:%h %s",
                branch,
            ],
            capture_output=True,
            text=True,
            timeout=5,
            check=True,
        )
    except (subprocess.CalledProcessError,
            subprocess.TimeoutExpired) as exc:
        return {
            "branch": branch,
            "since": since,
            "commit_count": 0,
            "commits": [f"git error: {exc}"],
        }

    lines = [
        line for line in result.stdout.splitlines() if line
    ]
    return {
        "branch": branch,
        "since": since,
        "commit_count": len(lines),
        "commits": lines,
    }


# resources and prompts come next
# standup_server.py (continued)

@mcp.resource("recent_commits://main")
def recent_commits_main() -> str:
    """Last 10 commits on the main branch, plain text.

    Resources are pulled by the host opportunistically.
    They are not invoked by the model the way tools are.
    """
    result = subprocess.run(
        [
            "git", "log",
            "-n", "10",
            "--pretty=format:%h %ad %s",
            "--date=short",
            "main",
        ],
        capture_output=True,
        text=True,
        timeout=5,
    )
    return result.stdout or "(no commits found)"


@mcp.prompt("standup_template")
def standup_template(focus: str = "shipping work") -> str:
    """Reusable standup question exposed as a prompt
    template. Surfaces as a slash command in clients that
    expose prompts (e.g. /standup_template in Claude Code).
    """
    return (
        f"Summarize what I worked on yesterday, focusing on "
        f"{focus}. Use the summarize_standup tool to get the "
        f"git log, then write a one-paragraph standup note."
    )


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

Transports et authentification

Lors de la phase des Transports et de l’Authentification, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Enregistrez l’ID de la requête, l’ID du modèle et le temps de réponse pour chaque appel. Sans ces traces, les erreurs intermittentes du fournisseur ressemblent à des bugs de l’application.

# bottom of standup_server.py

if __name__ == "__main__":
    # Default transport is stdio. The host (Claude Code,
    # Cursor, Claude Desktop, etc.) launches this script
    # as a subprocess and talks to it over stdin/stdout.
    # No port, no TLS, no auth. The trust boundary is
    # whoever launched the host.
    mcp.run()

    # To expose the same server over the network instead,
    # use Streamable HTTP. SSE was deprecated in the
    # March 2025 spec update. Do not use it for new code.
    #
    # Production HTTP also needs an auth layer in front.
    # OAuth 2.1 with Dynamic Client Registration is the
    # current pattern. See Week 22 for the full flow.
    #
    # mcp.run(
    #     transport="streamable-http",
    #     host="0.0.0.0",
    #     port=8000,
    # )

Le cycle de développement local

Lors de la phase du cycle de développement local, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Enregistrez l’ID de la demande, l’ID du modèle et le temps de latence pour chaque appel. Sans cette trace, les erreurs intermittentes du fournisseur ressemblent à des bugs de l’application.

npx @modelcontextprotocol/inspector python standup_server.py

Même serveur, trois clients

Lors du travail sur l’étape « Même serveur, trois clients », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Enregistrez l’ID de la demande, l’ID du modèle et le temps de réponse pour chaque appel. Sans cette trace, les erreurs intermittentes du fournisseur ressemblent à des bugs de l’application. Lors du travail sur l’étape « Même serveur, trois clients », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Notez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés.

{
  "mcpServers": {
    "standup-helper": {
      "command": "python",
      "args": ["/Users/you/code/standup_server.py"]
    }
  }
}
{
  "mcpServers": {
    "standup-helper": {
      "command": "python",
      "args": ["/Users/you/code/standup_server.py"]
    }
  }
}
{
  "mcpServers": {
    "standup-helper": {
      "command": "python",
      "args": ["/Users/you/code/standup_server.py"]
    }
  }
}

À quoi ne pas utiliser MCP

L’étape « À quoi ne pas utiliser » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript exemplaire, un cas d’échec et la note de rollback avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Fixez l’interpréteur ainsi que le fichier de verrouillage des dépendances avant d’enseigner la boucle. Les différences entre l’ordinateur portable et l’environnement CI sont la cause la plus fréquente de dysfonctionnements silencieux dans les démos API.

Le protocole est simple. Le changement est important.

Le protocole de phase « Small » fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours optimal et celui de récupération. Les tentatives répétées, les contrôles humains et le traitement des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Fixez l’interpréteur ainsi que le fichier de verrouillage des dépendances avant d’expliquer la boucle. Les écarts entre l’ordinateur portable et les environnements CI sont la cause la plus fréquente de dysfonctionnement silencieux lors des démonstrations API.

Continuer la lecture

La phase « Continuer la lecture » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit pointer vers une seule responsabilité plutôt qu’un processus embrouillé. Fixez l’interpréteur ainsi que le fichier de verrouillage des dépendances avant d’expliquer la boucle. Les variations entre l’ordinateur portable et les environnements CI sont la cause la plus fréquente de dysfonctionnement silencieux dans les démos API. La phase « Continuer la lecture » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’une démo à des environnements partagés.

Liste de contrôle opérationnelle

Lors de l’étape du tableau de contrôle opérationnel, notez d’abord les conditions requises, le signal de succès et ce qui se passe en cas d’échec partiel. Ce tableau garantit l’honnêteté des modifications ultérieures du code.

Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux éléments générés, définez des vérifications de succès et refusez toute exécution partielle silencieuse.

Enregistrez l’ID de la demande, l’ID du modèle et le temps de réponse pour chaque appel. Sans ce suivi, les erreurs intermittentes du fournisseur sont prises pour des bugs de l’application.

Fournissez des outils dotés de schémas restreints et de mentions explicites concernant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.

Ajoutez un test de base qui exécute le parcours critique dans l’environnement CI à l’aide de fichiers de configuration, et non d’API payantes en ligne, chaque fois que le budget le permet.

Dokumentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement.

Au préalable de promouvoir l’ensemble technique, figez les versions, conservez une transcription exemplaire pour le parcours critique, et vérifiez les étapes de rollback. Les environnements partagés nécessitent des limites de fréquence, des contrôles d’attribution et un responsable clair pour la rotation des secrets. Préférez une fiabilité simple à des démonstrations originales mais peu fiables.

Note de batch pour 91ba71830d6a : gardez les clés du fournisseur hors du répertoire de code, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers d’évaluation afin que les remplacements de modèles ultérieurs restent comparables.

Lors de la réalisation de l’étape 0 des notes de renforcement, notez d’abord les éléments essentiels : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une responsabilité précise plutôt qu’un processus embrouillé.

Détail de renforcement 0/811 : mesurez le temps d’exécution, la catégorie de l’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver la modification en vous basant sur un ensemble de critères prédéfinis plutôt que sur des observations subjectives.

L’étape 1 des notes de renforcement fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Recueillez un exemple idéal de fonctionnement, un cas d’échec et une note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite des surprises lors du passage de l’environnement de démonstration à des environnements partagés.

Détail de renforcement 1/811 : mesurez le temps d’exécution, la classe d’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver le changement en vous basant sur un ensemble de questions prédéfini plutôt que sur des anecdotes.

Pour la deuxième étape de la note de renforcement, définissez les entrées, le responsable de l’étape et les critères d’achèvement avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure.

Détail de renforcement 2/811 : mesurez le temps d’exécution, la classe d’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver le changement en vous basant sur un ensemble de questions prédéfini plutôt que sur des anecdotes.