opensearch-mcp-server 2.0.10__py3-none-any.whl → 2.0.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opensearch-mcp-server
3
- Version: 2.0.10
3
+ Version: 2.0.12
4
4
  Summary: MCP Server for interacting with Elasticsearch and OpenSearch
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -216,12 +216,14 @@ Requires-Dist: tomli==2.2.1
216
216
  Description-Content-Type: text/markdown
217
217
 
218
218
 
219
- # Elasticsearch/OpenSearch MCP Server
219
+ <!-- mcp-name: io.github.cr7258/elasticsearch-mcp-server -->
220
220
 
221
- [![smithery badge](https://smithery.ai/badge/elasticsearch-mcp-server)](https://smithery.ai/server/elasticsearch-mcp-server)
221
+ # Elasticsearch/OpenSearch MCP Server
222
222
 
223
223
  [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/cr7258-elasticsearch-mcp-server-badge.png)](https://mseep.ai/app/cr7258-elasticsearch-mcp-server)
224
224
 
225
+ [![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/cr7258/elasticsearch-mcp-server)](https://archestra.ai/mcp-catalog/cr7258__elasticsearch-mcp-server)
226
+
225
227
  ## Overview
226
228
 
227
229
  A Model Context Protocol (MCP) server implementation that provides Elasticsearch and OpenSearch interaction. This server enables searching documents, analyzing indices, and managing cluster through a set of tools.
@@ -267,7 +269,20 @@ https://github.com/user-attachments/assets/f7409e31-fac4-4321-9c94-b0ff2ea7ff15
267
269
 
268
270
  ## Configure Environment Variables
269
271
 
270
- Copy the `.env.example` file to `.env` and update the values accordingly.
272
+ The MCP server supports the following environment variables for authentication:
273
+
274
+ ### Basic Authentication (Username/Password)
275
+ - `ELASTICSEARCH_USERNAME`: Username for basic authentication
276
+ - `ELASTICSEARCH_PASSWORD`: Password for basic authentication
277
+ - `OPENSEARCH_USERNAME`: Username for OpenSearch basic authentication
278
+ - `OPENSEARCH_PASSWORD`: Password for OpenSearch basic authentication
279
+
280
+ ### API Key Authentication (Elasticsearch only) - Recommended
281
+ - `ELASTICSEARCH_API_KEY`: API key for [Elasticsearch](https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys) or [Elastic Cloud](https://www.elastic.co/docs/deploy-manage/api-keys/elastic-cloud-api-keys) Authentication.
282
+
283
+ ### Other Configuration
284
+ - `ELASTICSEARCH_HOSTS` / `OPENSEARCH_HOSTS`: Comma-separated list of hosts (default: `https://localhost:9200`)
285
+ - `ELASTICSEARCH_VERIFY_CERTS` / `OPENSEARCH_VERIFY_CERTS`: Whether to verify SSL certificates (default: `false`)
271
286
 
272
287
  ## Start Elasticsearch/OpenSearch Cluster
273
288
 
@@ -292,7 +307,7 @@ You can access Kibana/OpenSearch Dashboards from http://localhost:5601.
292
307
  Using `uvx` will automatically install the package from PyPI, no need to clone the repository locally. Add the following configuration to 's config file `claude_desktop_config.json`.
293
308
 
294
309
  ```json
295
- // For Elasticsearch
310
+ // For Elasticsearch with username/password
296
311
  {
297
312
  "mcpServers": {
298
313
  "elasticsearch-mcp-server": {
@@ -309,6 +324,22 @@ Using `uvx` will automatically install the package from PyPI, no need to clone t
309
324
  }
310
325
  }
311
326
 
327
+ // For Elasticsearch with API key
328
+ {
329
+ "mcpServers": {
330
+ "elasticsearch-mcp-server": {
331
+ "command": "uvx",
332
+ "args": [
333
+ "elasticsearch-mcp-server"
334
+ ],
335
+ "env": {
336
+ "ELASTICSEARCH_HOSTS": "https://localhost:9200",
337
+ "ELASTICSEARCH_API_KEY": "<YOUR_ELASTICSEARCH_API_KEY>"
338
+ }
339
+ }
340
+ }
341
+ }
342
+
312
343
  // For OpenSearch
313
344
  {
314
345
  "mcpServers": {
@@ -332,7 +363,7 @@ Using `uvx` will automatically install the package from PyPI, no need to clone t
332
363
  Using `uv` requires cloning the repository locally and specifying the path to the source code. Add the following configuration to Claude Desktop's config file `claude_desktop_config.json`.
333
364
 
334
365
  ```json
335
- // For Elasticsearch
366
+ // For Elasticsearch with username/password
336
367
  {
337
368
  "mcpServers": {
338
369
  "elasticsearch-mcp-server": {
@@ -352,6 +383,25 @@ Using `uv` requires cloning the repository locally and specifying the path to th
352
383
  }
353
384
  }
354
385
 
386
+ // For Elasticsearch with API key
387
+ {
388
+ "mcpServers": {
389
+ "elasticsearch-mcp-server": {
390
+ "command": "uv",
391
+ "args": [
392
+ "--directory",
393
+ "path/to/src/elasticsearch_mcp_server",
394
+ "run",
395
+ "elasticsearch-mcp-server"
396
+ ],
397
+ "env": {
398
+ "ELASTICSEARCH_HOSTS": "https://localhost:9200",
399
+ "ELASTICSEARCH_API_KEY": "<YOUR_ELASTICSEARCH_API_KEY>"
400
+ }
401
+ }
402
+ }
403
+ }
404
+
355
405
  // For OpenSearch
356
406
  {
357
407
  "mcpServers": {
@@ -378,11 +428,15 @@ Using `uv` requires cloning the repository locally and specifying the path to th
378
428
  ### Option 1: Using uvx
379
429
 
380
430
  ```bash
381
- # export environment variables
431
+ # export environment variables (with username/password)
382
432
  export ELASTICSEARCH_HOSTS="https://localhost:9200"
383
433
  export ELASTICSEARCH_USERNAME="elastic"
384
434
  export ELASTICSEARCH_PASSWORD="test123"
385
435
 
436
+ # OR export environment variables (with API key)
437
+ export ELASTICSEARCH_HOSTS="https://localhost:9200"
438
+ export ELASTICSEARCH_API_KEY="<YOUR_ELASTICSEARCH_API_KEY>"
439
+
386
440
  # By default, the SSE MCP server will serve on http://127.0.0.1:8000/sse
387
441
  uvx elasticsearch-mcp-server --transport sse
388
442
 
@@ -405,11 +459,15 @@ uv run src/server.py elasticsearch-mcp-server --transport sse --host 0.0.0.0 --p
405
459
  ### Option 1: Using uvx
406
460
 
407
461
  ```bash
408
- # export environment variables
462
+ # export environment variables (with username/password)
409
463
  export ELASTICSEARCH_HOSTS="https://localhost:9200"
410
464
  export ELASTICSEARCH_USERNAME="elastic"
411
465
  export ELASTICSEARCH_PASSWORD="test123"
412
466
 
467
+ # OR export environment variables (with API key)
468
+ export ELASTICSEARCH_HOSTS="https://localhost:9200"
469
+ export ELASTICSEARCH_API_KEY="<YOUR_ELASTICSEARCH_API_KEY>"
470
+
413
471
  # By default, the Streamable HTTP MCP server will serve on http://127.0.0.1:8000/mcp
414
472
  uvx elasticsearch-mcp-server --transport streamable-http
415
473
 
@@ -1,8 +1,8 @@
1
1
  src/__init__.py,sha256=aNKcThftSLh9IjOTA-UUpoRzIm4R0WwXKGAzykwecmU,211
2
2
  src/server.py,sha256=BfMAgXTFV9C4waCWRro8Sfl6yXEXr2vJ7YoGY7HhMPY,5072
3
- src/version.py,sha256=QvVarwQu86KS14HXwAYbCqU1tjzA5eNjQxH2V34_iIU,23
4
- src/clients/__init__.py,sha256=3UezAt9422S-7BvMiCo2Y9pmATVutorwsIQXP_g_CkA,1221
5
- src/clients/base.py,sha256=r8VmD4FAc-_PgHpNX7Pj2a0Db2NgUtIQvTucsRVSEsA,4700
3
+ src/version.py,sha256=YxcVJt69vWKI0evK12acqeFbIE4EyTGUERB7swCM2HQ,23
4
+ src/clients/__init__.py,sha256=MUKeCxvAFzzVfQr4x1seB7cRVLtWAk7pb1-5tLG0T8g,1299
5
+ src/clients/base.py,sha256=tMNdKRsAG1dPHj7famwPvCXCONuT9jML-7FmWV9vXbs,5348
6
6
  src/clients/exceptions.py,sha256=NYF3KVw-9aAgCViin5OuBI6miMEPS5QsdHx6bcis1wc,2493
7
7
  src/clients/common/__init__.py,sha256=VgvgxFpESn2wAuJmH0XM_Ej2izI7dxK7QJe9wG4fmW0,211
8
8
  src/clients/common/alias.py,sha256=rB53TSld5x2vZyDNAwyEdnh1KWUXMSD7h5fSv_ubR2Q,759
@@ -18,8 +18,8 @@ src/tools/document.py,sha256=XZTVuk4di9VEwWMZN7jyDVnzoOiXkb4FBrXF44sVXTs,2052
18
18
  src/tools/general.py,sha256=whj1spjIb8SS75h843X6c3RTsrZcSm-66KVLlY7OEh0,817
19
19
  src/tools/index.py,sha256=7KNPtElTFelkjRSvdMqPBx9nx_9Uk01OnTMeVo7YeCs,1345
20
20
  src/tools/register.py,sha256=wrG2P6-YPW77bTg1j_ELp8omWRYsJjFeOHUy_unHe6Y,1344
21
- opensearch_mcp_server-2.0.10.dist-info/METADATA,sha256=iS_wfVrNJno7xllqp-pvVjVlV_2nvjq2cJGTJbZIMSE,20476
22
- opensearch_mcp_server-2.0.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- opensearch_mcp_server-2.0.10.dist-info/entry_points.txt,sha256=ImfJnUwMpQUBmu-1MeBG_P0dwamfXKQh82mBKW7tWNY,138
24
- opensearch_mcp_server-2.0.10.dist-info/licenses/LICENSE,sha256=DBsjuP5FR51d9kaUdXlVBuBv3cQ_I_adq9gefYQ9FcY,11339
25
- opensearch_mcp_server-2.0.10.dist-info/RECORD,,
21
+ opensearch_mcp_server-2.0.12.dist-info/METADATA,sha256=kmyxZ-X5L5_t8AMnPWLyydpPsiTG1aebimajRMtcD4E,22614
22
+ opensearch_mcp_server-2.0.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ opensearch_mcp_server-2.0.12.dist-info/entry_points.txt,sha256=ImfJnUwMpQUBmu-1MeBG_P0dwamfXKQh82mBKW7tWNY,138
24
+ opensearch_mcp_server-2.0.12.dist-info/licenses/LICENSE,sha256=DBsjuP5FR51d9kaUdXlVBuBv3cQ_I_adq9gefYQ9FcY,11339
25
+ opensearch_mcp_server-2.0.12.dist-info/RECORD,,
src/clients/__init__.py CHANGED
@@ -24,12 +24,14 @@ def create_search_client(engine_type: str) -> SearchClient:
24
24
  hosts = [host.strip() for host in hosts_str.split(",")]
25
25
  username = os.environ.get(f"{prefix}_USERNAME")
26
26
  password = os.environ.get(f"{prefix}_PASSWORD")
27
+ api_key = os.environ.get(f"{prefix}_API_KEY")
27
28
  verify_certs = os.environ.get(f"{prefix}_VERIFY_CERTS", "false").lower() == "true"
28
29
 
29
30
  config = {
30
31
  "hosts": hosts,
31
32
  "username": username,
32
33
  "password": password,
34
+ "api_key": api_key,
33
35
  "verify_certs": verify_certs
34
36
  }
35
37
 
src/clients/base.py CHANGED
@@ -24,6 +24,7 @@ class SearchClientBase(ABC):
24
24
  hosts = config.get("hosts")
25
25
  username = config.get("username")
26
26
  password = config.get("password")
27
+ api_key = config.get("api_key")
27
28
  verify_certs = config.get("verify_certs", False)
28
29
 
29
30
  # Disable insecure request warnings if verify_certs is False
@@ -39,8 +40,8 @@ class SearchClientBase(ABC):
39
40
 
40
41
  # Initialize client based on engine type
41
42
  if engine_type == "elasticsearch":
42
- # Get auth parameters based on elasticsearch package version
43
- auth_params = self._get_elasticsearch_auth_params(username, password)
43
+ # Get auth parameters based on elasticsearch package version and authentication method
44
+ auth_params = self._get_elasticsearch_auth_params(username, password, api_key)
44
45
 
45
46
  self.client = Elasticsearch(
46
47
  hosts=hosts,
@@ -64,20 +65,26 @@ class SearchClientBase(ABC):
64
65
  base_url=base_url,
65
66
  username=username,
66
67
  password=password,
68
+ api_key=api_key,
67
69
  verify_certs=verify_certs,
68
70
  )
69
71
 
70
- def _get_elasticsearch_auth_params(self, username: Optional[str], password: Optional[str]) -> Dict:
72
+ def _get_elasticsearch_auth_params(self, username: Optional[str], password: Optional[str], api_key: Optional[str]) -> Dict:
71
73
  """
72
74
  Get authentication parameters for Elasticsearch client based on package version.
73
75
 
74
76
  Args:
75
77
  username: Username for authentication
76
78
  password: Password for authentication
79
+ api_key: API key for authentication
77
80
 
78
81
  Returns:
79
82
  Dictionary with appropriate auth parameters for the ES version
80
83
  """
84
+ # API key takes precedence over username/password
85
+ if api_key:
86
+ return {"api_key": api_key}
87
+
81
88
  if not username or not password:
82
89
  return {}
83
90
 
@@ -97,20 +104,28 @@ class SearchClientBase(ABC):
97
104
  return {"basic_auth": (username, password)}
98
105
 
99
106
  class GeneralRestClient:
100
- def __init__(self, base_url: Optional[str], username: Optional[str], password: Optional[str], verify_certs: bool):
107
+ def __init__(self, base_url: Optional[str], username: Optional[str], password: Optional[str], api_key: Optional[str], verify_certs: bool):
101
108
  self.base_url = base_url.rstrip("/") if base_url else ""
102
109
  self.auth = (username, password) if username and password else None
110
+ self.api_key = api_key
103
111
  self.verify_certs = verify_certs
104
112
 
105
113
  def request(self, method, path, params=None, body=None):
106
114
  url = f"{self.base_url}/{path.lstrip('/')}"
115
+ headers = {}
116
+
117
+ # Add API key to Authorization header if provided
118
+ if self.api_key:
119
+ headers["Authorization"] = f"ApiKey {self.api_key}"
120
+
107
121
  with httpx.Client(verify=self.verify_certs) as client:
108
122
  resp = client.request(
109
123
  method=method.upper(),
110
124
  url=url,
111
125
  params=params,
112
126
  json=body,
113
- auth=self.auth
127
+ auth=self.auth if not self.api_key else None, # Use basic auth only if no API key
128
+ headers=headers
114
129
  )
115
130
  resp.raise_for_status()
116
131
  ct = resp.headers.get("content-type", "")
src/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.0.10"
1
+ __version__ = "2.0.12"