Custom Elasticsearch MCP Server

Custom Elasticsearch MCP Server

A high-performance MCP server that connects tools like Cursor to Elasticsearch clusters using public-key authorization instead of API keys. It provides optimized tools for searching data, listing indices, and inspecting cluster mappings or shards with support for concurrent requests.

Category
Visit Server

README

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 support
  • get_mappings - Get field mappings for any index
  • get_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 server
  • Dockerfile - Container build instructions
  • requirements.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! 🚀

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured