MCP (Model Context Protocol) devient la norme pour connecter les outils à l'IA

1. Vue d’ensemble

Les modèles de langage de grande taille (LLM) ne sont vraiment utiles que s’ils peuvent lire des données réelles et appeler des systèmes réels : chercher une commande, lire un ticket, exécuter une requête. Auparavant, chaque application IA écrivait sa propre façon d’intégrer chaque outil. Le Model Context Protocol (MCP) a été créé pour standardiser cette partie de la connexion.

Cet article explique ce qu’est MCP et pourquoi il suscite de l’intérêt. Ensuite, vous écrirez un petit serveur MCP en Spring Boot, configurerez un client pour l’appeler, et saurez quand ne pas utiliser MCP.

2. Qu’est-ce que MCP ?

MCP est un protocole ouvert. Il définit comment une application IA découvre et appelle des capacités externes : outils, données et modèles de prompt. Vous pouvez voir MCP comme un « port USB » pour l’IA. Tout appareil respectant la norme peut être branché sur n’importe quel hôte supportant cette norme et fonctionner.

2.1. Trois rôles principaux

  • Host : l’application avec laquelle l’utilisateur interagit, par exemple un assistant IA sur le bureau, un IDE ou un chatbot interne.
  • Client : composant situé dans l’hôte. Chaque client maintient une connexion un-à-un avec un serveur.
  • Server : programme fournissant des capacités à l’IA, par exemple un serveur lisant une base de données de commandes ou un serveur accédant au système de fichiers.

2.2. Trois types de « primitives » côté serveur

  • Tools : fonctions que le modèle peut décider d’appeler, comme findOrder ou cancelOrder.
  • Resources : données en lecture seule, comme le contenu d’un fichier ou un enregistrement de configuration, injectées dans le contexte.
  • Prompts : modèles de prompt prédéfinis que l’utilisateur peut choisir pour utiliser.

2.3. Le protocole sous-jacent

MCP utilise JSON-RPC 2.0. Les deux types de transport les plus courants sont : stdio, quand l’hôte lance le serveur comme un processus enfant, et HTTP, quand le serveur s’exécute à distance. Un appel d’outil ressemble à ceci :

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "findOrder",
    "arguments": { "orderId": "ORD-1001" }
  }
}

Le flux de travail de base se compose de trois étapes :

  1. Le client envoie initialize pour que les deux côtés échangent la version du protocole et les capacités prises en charge.
  2. Le client appelle tools/list pour obtenir la liste des outils, avec leur description et le schéma JSON de leurs paramètres.
  3. Quand le modèle décide d’utiliser un outil, le client envoie tools/call comme dans l’exemple ci-dessus, puis retourne le résultat au modèle.

Point important : le modèle n’appelle pas directement le serveur. L’hôte se place au milieu, il peut donc demander à l’utilisateur une confirmation avant d’exécuter un outil sensible.

3. Pourquoi MCP suscite-t-il de l’intérêt ?

3.1. Le problème N × M

Supposons qu’il y ait N applications IA et M systèmes à connecter. Sans norme commune, vous devez écrire N × M intégrations. Avec un protocole commun, chaque application n’a qu’à supporter MCP une fois, et chaque système n’a besoin que d’un serveur MCP. Le problème se réduit à N + M.

3.2. Séparation des responsabilités

L’équipe propriétaire du système de commandes écrit et exploite son serveur MCP. L’équipe qui crée le chatbot n’a qu’à pointer vers ce serveur. La logique métier, les droits d’accès et les journaux d’audit se trouvent à la bonne place, sans être dupliqués dans chaque prompt ou chaque application.

3.3. Ne pas être verrouillé à un fournisseur de modèle

L’appel de fonction de chaque fournisseur LLM a son propre format. MCP se situe à un niveau supérieur de ce format. Le serveur que vous écrivez aujourd’hui fonctionnera toujours si vous changez de modèle ou d’hôte.

3.4. L’écosystème s’agrandit

De plus en plus d’assistants IA, d’IDE et de frameworks prennent en charge MCP. Il existe des SDK pour de nombreux langages, Java ayant un SDK officiel et Spring AI disposant d’une intégration native. C’est pourquoi beaucoup considèrent MCP comme un candidat prometteur pour une norme de connexion d’outils. Cependant, le protocole est toujours en évolution, vous devez donc surveiller les spécifications lors de déploiements à long terme.

4. Écrire un serveur MCP en Spring Boot

Vous construirez un serveur fournissant deux outils pour rechercher et annuler des commandes, s’exécutant via stdio.

4.1. Dépendances

Spring AI fournit un starter pour le serveur MCP. Importez le BOM de Spring AI et utilisez la dernière version compatible avec votre Spring Boot 3.x :

<properties>
    <java.version>21</java.version>
    <spring-ai.version><!-- version Spring AI actuelle --></spring-ai.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-mcp-server</artifactId>
    </dependency>
</dependencies>

Le starter spring-ai-starter-mcp-server prend en charge le transport stdio. Si vous voulez exécuter le serveur via HTTP, Spring AI dispose de starters distincts pour Web MVC et WebFlux.

Note : Le nom de l’artifact Spring AI a changé entre les versions milestone. Vérifiez la documentation correspondant à votre version.

4.2. Domaine et outils

public record Order(String id, String customerName, double total, String status) {}
@Service
public class OrderTools {

    private final Map<String, Order> orders = new ConcurrentHashMap<>(Map.of(
            "ORD-1001", new Order("ORD-1001", "Nguyen Van An", 350_000, "SHIPPING"),
            "ORD-1002", new Order("ORD-1002", "Tran Thi Binh", 120_000, "PENDING")
    ));

    @Tool(description = "Recherche une commande par son code, retourne le client, le montant total et le statut")
    public Order findOrder(@ToolParam(description = "Code de commande, par exemple ORD-1001") String orderId) {
        Order order = orders.get(orderId);
        if (order == null) {
            throw new IllegalArgumentException("Commande non trouvée " + orderId);
        }
        return order;
    }

    @Tool(description = "Annule une commande. Peut uniquement annuler les commandes en statut PENDING")
    public String cancelOrder(@ToolParam(description = "Code de commande à annuler") String orderId) {
        Order order = findOrder(orderId);
        if (!"PENDING".equals(order.status())) {
            return "Impossible d'annuler : la commande est en statut " + order.status();
        }
        orders.put(orderId, new Order(order.id(), order.customerName(), order.total(), "CANCELLED"));
        return "Commande " + orderId + " annulée";
    }
}

Deux annotations jouent un rôle clé :

  • @Tool (paquet org.springframework.ai.tool.annotation) marque une méthode comme outil. La partie description est ce que le modèle lit pour décider d’appeler l’outil ou non. Plus la description est claire, plus le modèle fera le bon choix.
  • @ToolParam décrit chaque paramètre. Spring AI génère un schéma JSON à partir du type de paramètre et de cette description.

Notez que cancelOrder retourne un message au lieu de lever une exception en cas de violation des règles métier. Le modèle lit ce message et l’explique naturellement à l’utilisateur.

4.3. Enregistrer les outils auprès du serveur MCP

@SpringBootApplication
public class OrderMcpServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderMcpServerApplication.class, args);
    }

    @Bean
    ToolCallbackProvider orderToolProvider(OrderTools orderTools) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(orderTools)
                .build();
    }
}

MethodToolCallbackProvider analyse les méthodes annotées avec @Tool dans orderTools. L’auto-configuration du serveur MCP trouvera tous les beans ToolCallbackProvider et les exposera via tools/list.

4.4. Configuration pour stdio

spring.ai.mcp.server.name=order-mcp-server
spring.ai.mcp.server.version=0.0.1
spring.ai.mcp.server.stdio=true

spring.main.web-application-type=none
spring.main.banner-mode=off
logging.pattern.console=
logging.file.name=./logs/order-mcp-server.log

Avec stdio, stdout est le canal de transmission JSON-RPC. Tout ce qui est écrit sur stdout ruinera le protocole, y compris la bannière et les logs. Donc la configuration ci-dessus désactive la bannière, désactive les logs sur la console et les redirige vers un fichier.

Note : C’est l’erreur la plus courante quand on débute avec les serveurs MCP via stdio. Une seule ligne System.out.println pour déboguer peut causer une erreur d’analyse au client ou une déconnexion. Utilisez un logger qui écrit dans un fichier.

Construisez le fichier jar :

./mvnw clean package -DskipTests

5. Connexion du côté client

De nombreux hôtes configurent le serveur via un fichier JSON avec la clé mcpServers. Le nom du fichier et son emplacement dépendent de chaque hôte :

{
  "mcpServers": {
    "orders": {
      "command": "java",
      "args": ["-jar", "/opt/mcp/order-mcp-server.jar"]
    }
  }
}

Au démarrage, l’hôte exécute la commande java -jar ... comme un processus enfant, envoie initialize puis tools/list. Vous demandez : « La commande ORD-1002 peut-elle toujours être annulée ? Si oui, veuillez l’annuler pour moi. » Le modèle appellera findOrder puis cancelOrder. Le résultat retourné pour le deuxième appel ressemble à :

{"content":[{"type":"text","text":"Commande ORD-1002 annulée"}],"isError":false}

En général, l’hôte affiche une boîte de dialogue de confirmation avant d’exécuter l’outil. Vous devriez conserver ce comportement pour les outils ayant des effets secondaires comme cancelOrder.

Si vous voulez que votre application Spring joue le rôle de client, Spring AI dispose également d’un starter client MCP. Ce starter transforme les outils des serveurs externes en outils utilisables avec ChatClient.

6. Tester le comportement des outils

Les outils ne sont que des méthodes Java ordinaires, vous pouvez donc les tester sans démarrer MCP :

class OrderToolsTest {

    private final OrderTools tools = new OrderTools();

    @Test
    void shouldCancelPendingOrder() {
        String result = tools.cancelOrder("ORD-1002");

        assertThat(result).isEqualTo("Commande ORD-1002 annulée");
        assertThat(tools.findOrder("ORD-1002").status()).isEqualTo("CANCELLED");
    }

    @Test
    void shouldRefuseToCancelShippingOrder() {
        assertThat(tools.cancelOrder("ORD-1001"))
                .contains("Impossible d'annuler")
                .contains("SHIPPING");
    }

    @Test
    void shouldFailWhenOrderNotFound() {
        assertThatThrownBy(() -> tools.findOrder("ORD-9999"))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessageContaining("ORD-9999");
    }
}

Ces trois tests couvrent le flux de succès, les règles métier et le cas où la commande n’est pas trouvée. Le SDK gère déjà la partie protocole. Ce que vous devez vraiment assurer, c’est que la logique métier retourne le résultat correct et des messages clairs pour le modèle.

Pour des tests end-to-end, vous pouvez utiliser des outils d’inspection pour MCP. Ils permettent de lister les outils et de les tester manuellement.

7. Application pratique : ce qu’il faut considérer

  • Concevez les outils selon la logique métier, pas selon les tables. findOrder est meilleur qu’un outil executeSql universel. Un outil spécifique est à la fois plus facile à contrôler en matière de permissions et aide le modèle à faire le bon choix.
  • Privilèges minimaux. Le serveur doit utiliser un compte avec exactement les droits nécessaires. Séparez les outils de lecture et les outils d’écriture, et envisagez d’activer les outils d’écriture uniquement dans certains environnements.
  • Attention à l’injection de prompt. Les données retournées par les outils, par exemple les notes saisies par les clients, peuvent contenir des instructions visant à contrôler le modèle. Ne laissez pas les résultats d’un outil déclencher automatiquement des actions dangereuses sans confirmation.
  • Utilisez uniquement des serveurs de confiance. Un serveur MCP tiers s’exécutant via stdio est un processus sur votre machine, avec vos droits. Les descriptions d’outils peuvent également contenir du contenu malveillant. Lisez le code source ou utilisez uniquement des sources de confiance.
  • Authentification pour les serveurs distants. Lors de l’exécution via HTTP, placez le serveur derrière un mécanisme d’authentification approprié et enregistrez les appels d’outils dans les journaux d’audit.
  • Gardez un nombre raisonnable d’outils. Chaque outil consomme du contexte pour sa description. Trop d’outils rendent facile pour le modèle de faire le mauvais choix.

8. Quand NE PAS utiliser MCP

  • Petites applications avec un seul modèle et quelques fonctions. L’appel de fonction direct du framework, par exemple @Tool utilisé directement avec ChatClient, est plus simple. Vous n’avez pas besoin d’un processus supplémentaire ni d’une couche de protocole.
  • Flux de traitement fixe, sans qu’un modèle ait besoin de décider. Si l’étape 1 appelle toujours l’API A et l’étape 2 appelle toujours l’API B, écrivez simplement du code normal. Ne confiez pas à un LLM ce qu’un simple if fait mieux.
  • Exigences de très faible latence ou de forte déterministe. Chaque cycle modèle → client → serveur ajoute de la latence. Les résultats du modèle ne sont pas non plus entièrement déterministes.
  • Opérations irréversibles sans révision. Les virements ou les suppressions en masse ne doivent pas être exposés comme des outils automatiques. Si c’est absolument nécessaire, incluez toujours une étape de confirmation.
  • Vous avez besoin d’une API pour que d’autres systèmes l’appellent. MCP est conçu pour servir l’IA. Entre les services, REST, gRPC ou la messagerie restent des choix appropriés.

9. Conclusion

MCP résout un problème très réel : connecter l’IA aux outils et aux données de manière cohérente, au lieu que chaque application écrive sa propre approche. Grâce au modèle hôte-client-serveur, aux trois primitives tools/resources/prompts et à la base JSON-RPC, un serveur que vous écrivez peut être réutilisé sur de nombreux hôtes différents.

Avec Spring AI, écrire un serveur MCP ne nécessite que quelques annotations @Tool, un bean ToolCallbackProvider et la bonne configuration pour stdio. La partie difficile se trouve ailleurs : concevoir des outils spécifiques et clairs, mettre en place des permissions strictes et se protéger contre l’injection de prompt. Vous devez aussi être lucide pour reconnaître les cas où le code ordinaire reste une meilleure solution.

mcpaispring-aispring-boottech-trends