Introduction
Les modèles de langage de grande taille (LLM) excellent dans la compréhension du langage naturel, mais restent isolés sans contexte. Le Model Context Protocol (MCP) corrige cela en agissant comme un port USB-C pour les applications d’IA : une façon standard de brancher un LLM à des sources de données et des outils.
Plutôt que de câbler votre modèle directement à une API spécifique, MCP définit un protocole où les clients (agents) demandent des informations et où les serveurs les fournissent via des ressources et des outils bien définis. C’est ouvert, indépendant du langage et déjà compatible avec une liste croissante d’intégrations.
Cet article présente MCP pour les développeurs qui peinent avec le Query DSL d’Elasticsearch. Nous allons voir comment lancer le serveur MCP expérimental pour Elasticsearch, le brancher à Claude Desktop, et interroger vos index en langage naturel (anglais). Si vous aimez bricoler avec des serveurs et des conteneurs, vous allez être servi : pas de jargon managérial, juste du code et des ports.
Qu’est-ce que MCP ?
Au cœur du protocole, MCP standardise la manière dont une application apporte du contexte à un LLM. La documentation officielle le décrit comme « un protocole ouvert qui normalise la façon dont les applications fournissent du contexte aux modèles de langage ».
MCP, c’est comme brancher un ordinateur portable sur une station d’accueil : une fois connecté, il accède à vos disques, écrans et câbles réseau.
En termes d’IA, la “dock” expose :
-
des intégrations prêtes à l’emploi pour les systèmes courants,
-
une manière standardisée de créer vos propres intégrations,
-
la possibilité de passer d’une application à l’autre tout en gardant le contexte.
Le dépôt GitHub modelcontextprotocol/servers illustre cette philosophie. On y trouve des implémentations de référence, ainsi que des liens vers des serveurs communautaires. Chaque serveur est construit à l’aide d’un SDK MCP — disponibles officiellement en C#, Go, Java, Kotlin, Python, Ruby, Rust, Swift et TypeScript — montrant comment donner aux LLM un accès sécurisé et contrôlé aux outils et aux sources de données.
MCP vs sans MCP
Pourquoi combiner MCP avec Elasticsearch ?
Pour beaucoup de développeurs, le Query DSL d’Elasticsearch est puissant mais verbeux. Même une tâche simple, comme filtrer sur une adresse IP client dans les logs d’un serveur web, peut nécessiter plusieurs lignes de JSON.
Le blog Elastic Labs imagine une autre expérience : et si interagir avec vos données était aussi simple que discuter avec un collègue ?
Avec MCP, vous pouvez demander :
“Je veux voir combien d’événements de log concernent l’IP 83.149.9.216 dans idx_mondai_logs”
et obtenir une réponse précise — sans écrire de requêtes. MCP agit comme un traducteur entre langage naturel et appels d’API, transformant des demandes complexes en une conversation naturelle.
Exemple de question
Sous le capot
Première Itération
AI tries to construct queries DSL itself to find IP
Première Réponse Intermédiaire
{ "body": { "size": 0, "query": { "match": { "clientip": "83.149.9.216" } } }, "index": "idx_mondai_logs" }
Deuxième Itération
AI will search for log events related to the IP address 83.149.9.216 in the idx_mondai_logs data stream.
{ "body": { "size": 0, "query": { "multi_match": { "type": "phrase", "query": "83.149.9.216", "fields": [ "*" ] } } }, "index": "idx_mondai_logs" }
Deuxième Réponse Intermédiaire
After first DSL query AI finds any logs with that specific IP format. Let me try a different approach, as the IP might be stored in a different field or format:
{ "took": 9, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 23, "relation": "eq" }, "max_score": null, "hits": [] } }
Troisième Itération
Let’s see a sample of these logs to understand their structure:
{ "body": { "size": 0, "query": { "multi_match": { "type": "phrase", "query": "83.149.9.216", "fields": [ "*" ] } } }, "index": "idx_mondai_logs" }
Third Intermediate Response
{ "took": 4, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 23, "relation": "eq" }, "max_score": 1.0, "hits": [ { "_index": ".ds-idx_mondai_logs-2025.03.02-000001", "_id": "KsopV5UBCxHQM_fULRuM", "_score": 1.0, "_source": { "@timestamp": "2025-03-02T14:01:08.809Z", "input": { "type": "filestream" }, "fields": { "log_type": "mondai-logs" }, "agent": { "version": "8.17.2", "ephemeral_id": "7ff5e048-352d-4360-9fb1-a09da8cb6d8a", "id": "1506f876-df4a-4d97-8032-68ef7ab7ce0d", "name": "LAPTOP-FTPONOOH", "type": "filebeat" }, "ecs": { "version": "8.0.0" }, "host": { "ip": [ "fe80::b0a6:dd21:d67f:6d7f", "169.254.106.150", "fe80::659f:a6f7:4f44:5e9d", "169.254.20.165", "fe80::becc:5e21:ca9:e225", "169.254.97.75", "fe80::302a:179a:4b7a:5271", "169.254.145.189", "2a02:842a:853b:9401:848c:4b52:e188:dcce", "2a02:842a:853b:9401:702e:9878:3da1:2f61", "fe80::1c56:ada8:e621:954e", "192.168.1.43", "fe80::4605:9710:601a:a5d7", "169.254.85.196" ], "mac": [ "00-FF-C0-E1-92-72", "E8-6F-38-7B-02-E5", "E8-6F-38-7B-02-E6", "E8-D8-D1-DB-B2-17", "EA-6F-38-7B-02-E5", "FA-6F-38-7B-02-E5" ], "hostname": "LAPTOP-FTPONOOH", "architecture": "x86_64", "os": { "build": "26100.3194", "type": "windows", "platform": "windows", "version": "10.0", "family": "windows", "name": "Windows 11 Home", "kernel": "10.0.26100.3194 (WinBuild.160101.0800)" }, "name": "laptop-ftponooh", "id": "5e7a79c8-138b-4f24-95ce-64956a0ef013" }, "log": { "offset": 0, "file": { "path": "C:\\Program Files\\Filebeat\\app_logs\\apache_logs.log", "idxhi": "3211264", "idxlo": "26742", "vol": "1479696651" } }, "message": "83.149.9.216 - - [17/May/2015:10:05:03 +0000] \"GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1\" 200 203023 \"http://semicomplete.com/presentations/logstash-monitorama-2013/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36\"" } } ] } }
Résultat
Explication
MCP repose sur deux rôles :
-
Clients : les agents (ex. Claude Desktop) qui interprètent l’intention utilisateur et décident quels outils appeler.
-
Serveurs : ils exposent les ressources et outils au-dessus des systèmes existants. Ils gèrent la connexion à Elasticsearch, listent les index, récupèrent les mappings et exécutent les requêtes.
Un serveur MCP connecté à Elasticsearch permet donc à un agent d’explorer, interroger et analyser des index en temps réel.
Les agents orchestrent plusieurs outils (list_indices, get_mappings, search…) et ajustent les requêtes à la volée, en gardant le contexte conversationnel.
C’est de la recherche interactive, pas une simple RAG (retrieval-augmented generation).
Le serveur MCP Elasticsearch
Elastic maintient un serveur MCP expérimental qui relie directement vos agents à vos données. Une fois lancé, il expose plusieurs outils:
Outil | Description |
---|---|
list_indices | Lister tous les index Elasticsearch disponibles |
get_mappings | Récupérer le mapping des champs d’un index |
search | Effectuer une recherche via Query DSL |
esql | Exécuter des requêtes SQL-like (ESQL) et renvoyer des résultats tabulaires |
get_shards | Obtenir des infos sur les shards et leur allocation |
Ces outils passent par les transports MCP supportés (stdio, HTTP streamable, optionnellement SSE).
Le serveur est distribué en image Docker (docker.elastic.co/mcp/elasticsearch
), configurable via variables d’environnement : ES_URL
pour l’URL du cluster + ES_API_KEY
ou identifiants basiques.
Exemple (mode stdio) :
“docker run -i –rm -e ES_URL -e ES_API_KEY
docker.elastic.co/mcp/elasticsearch stdio“
Exemple (mode HTTP avec streaming) :
“docker run –rm -e ES_URL -e ES_API_KEY -p 8080:8080
docker.elastic.co/mcp/elasticsearch http“
⚠️ Ce serveur est expérimental. Attendez-vous à des changements rapides. Versions supportées : 8.x et 9.x.
Connexion avec Claude Desktop
Claude Desktop embarque déjà un client MCP.
Dans Settings → Developer → MCP Servers, ajoutez une nouvelle entrée. Pour le mode stdio, la config ressemble à ceci :
{ "mcpServers": { "elasticsearch-mcp-server": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "ES_URL", "-e", "ES_API_KEY", "docker.elastic.co/mcp/elasticsearch", "stdio" ], "env": { "ES_URL": "https://your-cluster:9200", "ES_API_KEY": "your-api-key" } } } }
Dès que vous démarrez une conversation, l’agent se connecte automatiquement. La première fois que vous posez une question (ex. “Trouve les commandes de plus de 500 € du mois dernier”), l’agent peut :
-
appeler
list_indices
pour trouver l’index, -
get_mappings
pour comprendre les champs, -
puis
search
avec une requête DSL construite.
De votre côté, vous discutez. MCP orchestre.
Exemple en code (Python)
Si vous préférez la ligne de commande aux interfaces graphiques, vous pouvez interagir avec un serveur MCP par programmation. L’extrait Python suivant utilise la bibliothèque mcp-client
(un exemple encore en cours de développement) pour exécuter directement les outils list_indices
et search
.
Ce code suppose que le serveur est accessible via l’endpoint HTTP streamable : http://localhost:8080/mcp
import asyncio from mcp_client import MCPClient # hypothetical client library async def main(): # Connect to MCP server client = MCPClient( url="http://localhost:8080/mcp", auth=("Authorization", "ApiKey YOUR_API_KEY") ) # List indices indices = await client.call_tool("list_indices", {}) print("Available indices:") for idx in indices["indices"]: print(f" - {idx['index']} ({idx['docs_count']} docs)") # Search orders over 500 euros in last month (DSL built automatically) query = { "query": { "bool": { "filter": [ {"range": {"order_date": {"gte": "now-1M/M", "lte": "now/M"}}}, {"range": {"total": {"gte": 500}}} ] } } } response = await client.call_tool("search", {"index": "orders", "body": query}) for hit in response["hits"]: order = hit["_source"] print(f"Order {order['id']} total={order['total']} date={order['order_date']}") if __name__ == "__main__": asyncio.
Dans un agent en production, le modèle générerait la requête JSON DSL à votre place. Ici, nous la construisons manuellement pour montrer comment MCP transmet les arguments. Vous pouvez aussi tester l’outil esql si vous préférez le nouveau langage de type SQL d’Elastic.
Conclusion
Pour les développeurs qui redoutent le JSON DSL verbeux, MCP + Elasticsearch change la donne. Vous pouvez dialoguer avec vos index via une interface standardisée, tout en gardant la puissance de l’API native.
-
MCP est ouvert, extensible, multi-langage.
-
Les serveurs de référence montrent comment brancher fichiers, dépôts Git, etc.
-
Le serveur Elasticsearch expose des outils clés (
list_indices
,get_mappings
,search
…), rendant l’exploration des données quasi instantanée.
La techno est encore jeune (le serveur Elastic est marqué expérimental), mais la direction est claire : traiter les modèles comme clients à part entière de nos systèmes, pour mélanger recherche, analyse et exécution sans friction.
Si vous en avez assez de rédiger des requêtes DSL à la main, testez MCP. Branchez votre modèle à vos données… et commencez à poser vos questions comme un humain.