Skip to content

Commit 0151f16

Browse files
authored
Building an Elasticsearch MCP Server for AI agents like Claude Desktop (#46)
* Building an Elasticsearch MCP Server for AI agents like Claude Desktop * rename title * added introduction * wrap up article
1 parent 2bb62e4 commit 0151f16

File tree

2 files changed

+298
-0
lines changed

2 files changed

+298
-0
lines changed
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
---
2+
layout: post
3+
comments: true
4+
title: Integrating Elasticsearch with AI agents through Model Context Protocol
5+
excerpt: Building an Elasticsearch MCP Server for AI agents like Claude Desktop
6+
categories: genai
7+
tags: [elasticsearch,mcp]
8+
toc: true
9+
img_excerpt:
10+
---
11+
12+
Large Language Models (LLMs) are getting better every day at understanding all sorts of data, but they still suffer from knowledge cut-off when dealing with data that were not part of their pre-training. By integrating LLMs with external systems and knowledge bases, LLMs could achieve their true potential as they allow users to query and analyze complex data with natural conversations. [Model Context Protol (MCP)](https://modelcontextprotocol.io/) is one way of enable LLMs and AI assistants like Claude Desktop to perform actions, query data, and leverage the capabilities of other applications.
13+
14+
In this blog post, we explore how to implement in Python using the `fastmcp` library an MCP server for Elasticsearch that enables Claude Desktop (or any AI Agent) to directly query and analyze data from an Elasticsearch cluster. We'll then see how to configure Claude Desktop to use this server.
15+
16+
## What is MCP?
17+
18+
The Model Context Protocol (MCP) is a standardized interface that allows LLMs like Claude to interact with external systems. It creates a bridge between AI assistants and various data stores, tools, and services while maintaining a consistent communication pattern.
19+
20+
As shown in the diagram, MCP enables a standardized way for AI applications to interact with:
21+
- Data stores (databases, NoSQL databases)
22+
- CRM systems
23+
- Version control software
24+
- And potentially any external service with an appropriate MCP server
25+
26+
![MCP]({{ "/assets/2025/05/20250518-mcp-architecture.svg" | absolute_url }}){: .center-image }
27+
28+
Furthermore, using the MCP Approach to integreate AI agents with externalo systems has the following benefits:
29+
30+
1. **Standardization**: MCP provides a consistent interface for LLMs and AI agent to interact with external systems.
31+
2. **Separation of Concerns**: The LLM focuses on understanding and generating responses, while the MCP server handles the specifics of interacting with the target system (in this case, Elasticsearch).
32+
3. **Security**: Authentication details are managed by the MCP server, not exposed to the model.
33+
4. **Extensibility**: New tools can be easily added to the MCP server without changing the core integration.
34+
35+
36+
## Building an MCP Server
37+
38+
In this section we will build an MCP server for Elasticsearch
39+
40+
### Prerequisites
41+
42+
Before you start, make sure you have:
43+
44+
1. An Elasticsearch cluster accessible (either locally or remotely).
45+
2. Python installed (`3.8+ recommended`).
46+
3. `uv` for installing Python packages.
47+
4. Claude Desktop installed.
48+
49+
### Setup
50+
51+
We need to set up the environment that we will use to run our MCP server. We will use the `uv` tool, which helps manage Python environments, it automatically sets up the project files and manages the package dependencies.
52+
53+
In the project directory (e.g. `elasticsearch_mcp`), initialize a `uv` project:
54+
55+
```shell
56+
uv init
57+
uv venv
58+
source .venv/bin/activate
59+
```
60+
61+
The add the needed Python dependencies:
62+
63+
```shell
64+
uv add elasticsearch
65+
uv add python-dotenv
66+
uv add mcp
67+
```
68+
69+
### Connecting to Elasticsearch
70+
71+
Our MCP server needs to connect to the Elasticsearch cluster. We'll use environment variables to pass connection information and store them in a `.env` file. Here are few examples of content with different authentication methods:
72+
73+
Environment variables for API Key authentication
74+
75+
```shell
76+
# .env
77+
ES_URL=http://localhost:9200
78+
ES_API_KEY=your_base64_encoded_api_key
79+
ES_CA_CERT=/path/to/http_ca.crt # Optional, for HTTPS verification
80+
```
81+
82+
Environment variables for Basic Auth authentication
83+
84+
```shell
85+
# .env
86+
ES_URL=http://localhost:9200
87+
ES_USERNAME=your_username
88+
ES_PASSWORD=your_password
89+
ES_CA_CERT=/path/to/http_ca.crt # Optional, for HTTPS verification
90+
```
91+
92+
Next, in our python code we laod environment variables from `.env` and then create an Elasticsearch client instance with one of the following authentication methods:
93+
1. API key authentication
94+
2. Username/password authentication
95+
3. No authentication for local development
96+
97+
```python
98+
# server.py
99+
from elasticsearch import Elasticsearch
100+
from dotenv import load_dotenv
101+
102+
load_dotenv()
103+
104+
def createElasticsearchClient():
105+
# Access environment variables
106+
ES_URL = os.getenv('ES_URL')
107+
ES_API_KEY = os.getenv('ES_API_KEY') # base64 encoded api key
108+
ES_USERNAME = os.getenv('ES_USERNAME')
109+
ES_PASSWORD = os.getenv('ES_PASSWORD')
110+
ES_CA_CERT = os.getenv('ES_CA_CERT') # path to http_ca.crt file # Optional, for HTTPS verification
111+
112+
if ES_API_KEY:
113+
return Elasticsearch(hosts=[ES_URL], api_key=ES_API_KEY, ca_certs=ES_CA_CERT)
114+
if ES_USERNAME and ES_PASSWORD:
115+
return Elasticsearch(hosts=[ES_URL], basic_auth=(ES_USERNAME, ES_PASSWORD), ca_certs=ES_CA_CERT)
116+
return Elasticsearch(hosts=[ES_URL])
117+
118+
es = createElasticsearchClient()
119+
```
120+
121+
### Exposing Tools
122+
123+
Now, let's define the functions that will interact with the Elasticsearch and serve as our MCP tools.
124+
125+
First, we create an MCP server instance that allows Claude Desktop to interact with an Elasticsearch cluster:
126+
127+
```python
128+
# server.py
129+
from mcp.server.fastmcp import FastMCP
130+
131+
mcp = FastMCP("elasticsearch-mcp-server")
132+
```
133+
134+
Next, we define our main functions to list indices, get mappings, and perform searches. And annotate them with the `@mcp.tool()` decorator to register these Python functions as available tools for the MCP server.
135+
136+
#### 1. List Indices
137+
A function allowing Claude to retrieve all available indices in the Elasticsearch cluster.
138+
139+
```python
140+
# server.py
141+
@mcp.tool()
142+
def list_indices() -> List[str]:
143+
"""
144+
List all available Elasticsearch indices.
145+
146+
Returns:
147+
List of indices
148+
"""
149+
indices = es.indices.get_alias(index="*")
150+
index_names = list(indices.keys())
151+
return index_names
152+
```
153+
154+
155+
156+
#### 2. Get Mappings
157+
A function to enable Claude to understand the structure of data within a specific index by retrieving its mapping schema.
158+
159+
```python
160+
# server.py
161+
@mcp.tool()
162+
def get_mappings(index: str) -> dict:
163+
"""
164+
Get field mappings for a specific Elasticsearch index.
165+
166+
Args:
167+
index: Name of the Elasticsearch index to get mappings for
168+
169+
Returns:
170+
Mapping schema for the specified index
171+
"""
172+
mappings = es.indices.get_mapping(index=index)
173+
return mappings
174+
```
175+
176+
177+
#### 3. Search
178+
A function to allow Claude to execute Elasticsearch queries using the full power of the Elasticsearch Query DSL.
179+
180+
```python
181+
# server.py
182+
@mcp.tool()
183+
def search(index: str, queryBody: dict) -> dict:
184+
"""
185+
Perform an Elasticsearch search with the provided query DSL. Highlights are always enabled.
186+
187+
Args:
188+
index: Name of the Elasticsearch index to search
189+
queryBody: Complete Elasticsearch query DSL object that can include query, size, from, sort, etc.
190+
191+
Returns:
192+
Search result
193+
"""
194+
response = es.search(index=index, body=queryBody)
195+
return response
196+
```
197+
198+
## Using our MCP server
199+
200+
Our MCP server can be used by any AI assistant/IDE that supports MCP, including Claude Desktop.
201+
202+
### Configuring Claude Desktop
203+
204+
For Claude Deskto to connect to our Elasticsearch MCP server, we need to register the MCP server by adding it to Claude configuration file named `claude_desktop_config.json`. In MacOS, it should be available at `~/Library/Application\ Support/Claude/`.
205+
206+
The configuration for our Elasticsearch MCP server should look like this:
207+
208+
```json
209+
{
210+
"mcpServers": {
211+
"ElasticsearchServer": {
212+
"command": "/path/to/uv",
213+
"args": [
214+
"--directory",
215+
"/path/to/elasticsearch_mcp",
216+
"run",
217+
"server.py"
218+
]
219+
}
220+
}
221+
}
222+
```
223+
224+
This configuration tells Claude Desktop how to launch the Elasticsearch MCP server:
225+
1. It uses `uv` (a Python package manager/runner) to execute the server
226+
2. It specifies the working directory where the server code is located
227+
3. It runs the `server.py` script
228+
229+
230+
### Using the Elasticsearch MCP Server with Claude
231+
232+
With our MCP server implemented and Claude Desktop configured, we can now interact with our Elasticsearch cluster directly from Claude. For this, simply launch Claude Desktop and start a new conversation, that's it.
233+
234+
We ask Claude questions about our Elasticsearch cluster and it will use the `list_indices`, `get_mappings`, or `search` tools accordingly to fulfill the requests.
235+
236+
Here are few questions and answers:
237+
238+
**1. What are the indices available in my Elasticsearch cluster?**
239+
240+
```markdown
241+
I'll check what Elasticsearch indices are available in your cluster right now.
242+
243+
I can see that there is one index available in your Elasticsearch cluster:
244+
245+
- `hacker_news_posts`
246+
247+
Would you like me to explore this index further, such as checking its mapping schema or running some sample queries?
248+
```
249+
250+
**2. what are the mappings for the 'hacker_news_posts' index?**
251+
252+
```markdown
253+
I'll retrieve the mappings for the 'hacker_news_posts' index to show you its structure.
254+
255+
Here are the mappings for the 'hacker_news_posts' index:
256+
257+
### Top-level fields:
258+
- `by`: text field with keyword sub-field (for exact matching)
259+
- `id`: long (numeric) field
260+
- `score`: long (numeric) field
261+
- `time`: long (numeric) field, likely represents timestamps
262+
- `title`: text field with keyword sub-field
263+
- `type`: text field with keyword sub-field
264+
- `url`: text field with keyword sub-field
265+
266+
### Nested comments structure:
267+
- `comments`: object with the following properties:
268+
- `id`: text field with keyword sub-field
269+
- `level`: long (numeric) field
270+
- `parent_id`: text field with keyword sub-field
271+
- `text`: text field with keyword sub-field
272+
- `time_ago`: text field with keyword sub-field
273+
- `user`: text field with keyword sub-field
274+
275+
This appears to be an index storing Hacker News posts along with their associated comments. Each post has standard metadata like author (`by`), post ID, score, timestamp, title, type, and URL. The comments are stored as nested objects with their own structure including comment ID, nesting level, parent comment ID, comment text, relative time posted, and user who posted the comment.
276+
277+
Would you like me to show you how to query this data in a specific way?
278+
```
279+
280+
281+
## Conclusion
282+
283+
We have successfully built a basic Elasticsearch MCP server using `fastmcp` and integrated it with Claude Desktop. This allowed us to query and explore data from Elasticsearch using natural language within Claude.
284+
285+
Also note that Claude already provides a plethora of MCP servers that it can combine to let the user perform various tasks with simple natural language:
286+
287+
- Data exploration and analysis
288+
- Generating insights from large datasets
289+
- Creating visualizations based on query results
290+
- Answering complex questions about data stored in Elasticsearch
291+
292+
The standardization that MCP brings to AI development promises to make integrations more consistent, reliable, and easier to maintain as the AI ecosystem continues to evolve. By following the MCP pattern, you can create similar integrations for various data sources and services, expanding the capabilities of AI assistants like Claude without needing to modify the core LLM itself.
293+
294+
## That's all folks
295+
296+
I hope you enjoyed this article, feel free to leave a comment or reach out on twitter [@bachiirc](https://twitter.com/bachiirc).

assets/2025/05/20250518-mcp-architecture.svg

Lines changed: 2 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)