Custom Elasticsearch
A simple MCP server for Elasticsearch, designed for cloud environments where your public key is already authorized.
Custom Elasticsearch MCP Server
A simple MCP (Model Context Protocol) server for Elasticsearch designed for cloud environments where your public key is already authorized on the server.
Why This Custom Version?
No API Key Required - Unlike the official Elasticsearch MCP server that requires both ES_URL and ES_API_KEY, this version only needs the URL since your public key is already trusted on the cloud server.
Enhanced Tools - Better usability with optional parameters and improved defaults compared to the official version.
What This Does
This MCP server connects Cursor to your Elasticsearch cluster with 4 powerful tools:
list_indices- List all indices (optional pattern filter)search- Full Elasticsearch Query DSL supportget_mappings- Get field mappings for any indexget_shards- View cluster shard information
Quick Start
Build from Source
git clone https://github.com/M0-AR/Custom-Elasticsearch-MCP-Server.git
cd Custom-Elasticsearch-MCP-Server
docker build -t elasticsearch-mcp:latest .
2. Add to Cursor MCP Configuration
Add this to your .cursor/mcp.json file:
Configuration:
{
"mcpServers": {
"elasticsearch-custom": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--add-host=host.docker.internal:host-gateway",
"-e",
"ES_URL=http://host.docker.internal:9400",
"elasticsearch-mcp:latest"
]
}
}
}
3. Restart Cursor
Close and reopen Cursor. You should see the elasticsearch-custom server with 4 tools enabled.
Configuration
Environment Variables:
ES_URL- Your Elasticsearch URL (default:http://localhost:9400)MAX_CONNECTIONS- Maximum concurrent connections (default:100)MAX_KEEPALIVE_CONNECTIONS- Maximum keepalive connections (default:20)CONNECTION_TIMEOUT- Connection timeout in seconds (default:30)REQUEST_TIMEOUT- Request timeout in seconds (default:30)
For different Elasticsearch ports:
"ES_URL=http://host.docker.internal:9200"
For high-traffic environments:
"MAX_CONNECTIONS=200",
"MAX_KEEPALIVE_CONNECTIONS=50",
"CONNECTION_TIMEOUT=60",
"REQUEST_TIMEOUT=60"
Example Usage
Once connected in Cursor, you can:
- List all indices: "Show me all elasticsearch indices"
- Search data: "Search for sales data in hq.sales index"
- Get mappings: "What fields are in the hq.menuitems index?"
- Check cluster: "Show me the elasticsearch cluster status"
Comparison with Official Server
| Feature | Official Server | This Custom Server |
|---|---|---|
| Authentication | Requires ES_URL + ES_API_KEY | Only needs ES_URL (public key authorized) |
| list_indices | Requires indexPattern parameter | Optional parameter with "*" default |
| Tools Available | 4 tools (same functions) | 4 tools (enhanced usability) |
| Security | API key based | Public key authorization |
| Concurrency | Synchronous blocking | Async with connection pooling |
| Performance | Single request at a time | 100+ concurrent requests |
Concurrent Request Handling
This MCP server is designed to handle multiple parallel requests from multiple applications simultaneously using industry best practices:
Key Features:
✅ Async/Await Architecture - Non-blocking I/O for parallel request processing ✅ Connection Pooling - Reuses HTTP connections (up to 100 concurrent) ✅ HTTP/2 Support - Multiplexes multiple requests over single connection ✅ Configurable Limits - Adjust connection limits for your workload ✅ Thread-Safe - FastMCP handles concurrent tool execution safely
Performance Characteristics:
- Default: 100 concurrent connections, 20 keepalive connections
- Scalable: Configure up to 1000+ concurrent connections
- Efficient: Connection reuse reduces latency by ~50%
- Reliable: Proper timeout handling prevents connection exhaustion
Configuration for High Traffic:
{
"mcpServers": {
"elasticsearch-custom": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"--add-host=host.docker.internal:host-gateway",
"-e", "ES_URL=http://host.docker.internal:9400",
"-e", "MAX_CONNECTIONS=200",
"-e", "MAX_KEEPALIVE_CONNECTIONS=50",
"-e", "CONNECTION_TIMEOUT=60",
"-e", "REQUEST_TIMEOUT=60",
"elasticsearch-mcp:latest"
]
}
}
}
Testing Concurrent Requests:
# Test 10 parallel requests
for i in {1..10}; do
echo '{"jsonrpc": "2.0", "id": '$i', "method": "tools/call", "params": {"name": "list_indices", "arguments": {}}}' | \
python3 simple_elasticsearch_mcp.py &
done
wait
Files
simple_elasticsearch_mcp.py- Main MCP serverDockerfile- Container build instructionsrequirements.txt- Python dependencies
Manual Testing
Test the server directly:
python3 simple_elasticsearch_mcp.py
Test with JSON-RPC commands:
1. List all tools:
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}' | python3 simple_elasticsearch_mcp.py
2. List all indices:
echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_indices", "arguments": {}}}' | python3 simple_elasticsearch_mcp.py
3. Search for data:
echo '{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "search", "arguments": {"index": "hq.sales", "queryBody": {"query": {"match_all": {}}, "size": 3}}}}' | python3 simple_elasticsearch_mcp.py
4. Get index mappings:
echo '{"jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": {"name": "get_mappings", "arguments": {"index": "hq.menuitems"}}}' | python3 simple_elasticsearch_mcp.py
5. Check cluster shards:
echo '{"jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": {"name": "get_shards", "arguments": {}}}' | python3 simple_elasticsearch_mcp.py
Set custom Elasticsearch URL:
ES_URL="http://your-es-host:9200" python3 simple_elasticsearch_mcp.py
Troubleshooting
❌ "Connection refused" or "timed out" errors
Root Cause: The most common issue is Docker container networking when Elasticsearch is accessible via SSH tunnel.
Solution: Ensure these requirements are met:
1. SSH Tunnel Must Be Active
If your Elasticsearch is behind SSH tunnel (common for cloud deployments):
# Start SSH tunnel to forward port 9400
ssh -L 9400:localhost:9400 -N -f -l username your-server-ip
# Verify tunnel is working
curl -X GET "localhost:9400/_cluster/health?pretty"
2. Correct Docker Configuration
Your mcp.json should use exactly this configuration:
"elasticsearch-custom": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--add-host=host.docker.internal:host-gateway",
"-e",
"ES_URL=http://host.docker.internal:9400",
"elasticsearch-mcp:latest"
]
}
Key Points:
- ✅ Use
--add-host=host.docker.internal:host-gateway(not IP addresses) - ✅ Use
ES_URL=http://host.docker.internal:9400(not localhost) - ✅ SSH tunnel must be running before starting Cursor
3. Test Docker Connectivity
# Test if Docker can reach your Elasticsearch
docker run --rm --add-host=host.docker.internal:host-gateway alpine/curl \
curl -s http://host.docker.internal:9400/_cluster/health
4. Complete MCP Docker Test
Test the full MCP workflow with this comprehensive command:
# Full MCP server test with proper initialization
{
echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "test-client", "version": "1.0.0"}}}';
echo '{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}}';
echo '{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "list_indices", "arguments": {}}}';
} | docker run -i --rm --add-host=host.docker.internal:host-gateway -e ES_URL="http://host.docker.internal:9400" elasticsearch-mcp:latest
Expected Output:
- Initialization response with server info
- List of all Elasticsearch indices in JSON format
- No error messages
5. Alternative: Network Host Mode
If host-gateway doesn't work, try network host mode:
"args": [
"run", "-i", "--rm", "--network=host",
"-e", "ES_URL=http://localhost:9400",
"elasticsearch-mcp:latest"
]
❌ "Received request before initialization was complete"
Root Cause: MCP protocol requires proper initialization sequence.
Solution: Always initialize before calling tools:
# Correct sequence:
echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "test", "version": "1.0"}}}'
echo '{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}}'
echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "list_indices", "arguments": {}}}'
That's It!
Build → Add to config → Restart Cursor → Done! 🚀
관련 서버
Qdrant RAG MCP Server
A semantic search server for codebases using Qdrant, featuring intelligent GitHub issue and project management.
Search Intent MCP
Analyzes user search keyword intent for SEO support using the AI Search Intent API.
search-scrape
Self-hosted Stealth Scraping & Federated Search for AI Agents. A 100% private, free alternative to Firecrawl, Jina Reader, and Tavily. Featuring Universal Anti-bot Bypass + Semantic Research Memory, Copy-Paste setup
Unsplash
Search for pictures on Unsplash using the Unsplash API.
National Parks
Access real-time information about U.S. National Parks, including park details, alerts, and activities, via the National Park Service (NPS) API.
Rakuten Travel
Search for hotels and check their availability using the Rakuten Travel API.
Yandex Search
A web search server that uses the Yandex Search API.
USGS Quakes
Access earthquake data from the USGS Quakes API using natural language queries.
展会大数据服务
Query comprehensive exhibition information, including enterprise participation records, venue details, and exhibition search.
Sci-Hub MCP Server
Search and access academic papers from Sci-Hub by DOI, title, or keyword.