opensearch-mcp-server 2.0.2__py3-none-any.whl → 2.0.4__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.2
3
+ Version: 2.0.4
4
4
  Summary: MCP Server for interacting with Elasticsearch and OpenSearch
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -231,6 +231,10 @@ https://github.com/user-attachments/assets/f7409e31-fac4-4321-9c94-b0ff2ea7ff15
231
231
 
232
232
  ## Features
233
233
 
234
+ ### General Operations
235
+
236
+ - `general_api_request`: Perform a general HTTP API request. Use this tool for any Elasticsearch/OpenSearch API that does not have a dedicated tool.
237
+
234
238
  ### Index Operations
235
239
 
236
240
  - `list_indices`: List all indices.
@@ -1,22 +1,25 @@
1
1
  src/__init__.py,sha256=aNKcThftSLh9IjOTA-UUpoRzIm4R0WwXKGAzykwecmU,211
2
- src/server.py,sha256=BtNr3oKiRK1rbnocFIKzwpukY87_AylzKh_ffwP6Zr8,2153
2
+ src/server.py,sha256=Gf5sPXmuG4Jos82ks0LPFNWWbMGEIUfoKm8ibOHmx_A,2287
3
+ src/version.py,sha256=ZOg41aCgKEuObK5WhegikXektFWPJaeZ-TMDh0Ke95M,22
3
4
  src/clients/__init__.py,sha256=3UezAt9422S-7BvMiCo2Y9pmATVutorwsIQXP_g_CkA,1221
4
- src/clients/base.py,sha256=vTe4I62ruO2bEeSAag-2B5fJOWJDXllKbo8qA0h4VkM,2160
5
+ src/clients/base.py,sha256=MBAGepXyHPtdbtHhxFB8CamZ2ApWCBuOi_6-ey-MqX8,3298
5
6
  src/clients/exceptions.py,sha256=NYF3KVw-9aAgCViin5OuBI6miMEPS5QsdHx6bcis1wc,2493
6
7
  src/clients/common/__init__.py,sha256=VgvgxFpESn2wAuJmH0XM_Ej2izI7dxK7QJe9wG4fmW0,211
7
8
  src/clients/common/alias.py,sha256=rB53TSld5x2vZyDNAwyEdnh1KWUXMSD7h5fSv_ubR2Q,759
8
- src/clients/common/client.py,sha256=GD-V97Dj8c2XGUYt58vqCggkk-k8WJePPgngBDWO5aM,973
9
+ src/clients/common/client.py,sha256=khRO3osowTvoXnPscefUSuBYMrhOao2urOnRwqiUMbI,1041
9
10
  src/clients/common/cluster.py,sha256=pd5BVpqqDU6Lck3K704eEdhgFgzt9NstotWQLyG9zFM,401
10
11
  src/clients/common/document.py,sha256=ZzZiXDf_UhlN2FCmqW3drVjIZ07kGYP9yth_sgsJGPc,1623
12
+ src/clients/common/general.py,sha256=_1eS11Ha-JC1x1YoSu63zUWXKvYkwvN8RQOUM1fx39M,469
11
13
  src/clients/common/index.py,sha256=vyH5iXlJe5JLcDK6fhCCEPN-tgGm6zP5ilwGPdWCXbY,776
12
- src/tools/__init__.py,sha256=qiMRNUKlpNGnqbrkgBHGa7El1Pw_0a2qUJnuk_Q8LtY,324
14
+ src/tools/__init__.py,sha256=PGsXXpPubVnUbzXJG4keDhgjr0j6EnMNDs0aLqNIb4A,387
13
15
  src/tools/alias.py,sha256=p9TD4gXkGRGWHTYfvCg7G2hj-Uch9jwDXJNUY1hSD0Y,1376
14
16
  src/tools/cluster.py,sha256=XRAG-uxdfrieYX1ov_cBb66IYXaa8OoSWCUfXvNauy0,587
15
17
  src/tools/document.py,sha256=XZTVuk4di9VEwWMZN7jyDVnzoOiXkb4FBrXF44sVXTs,2052
18
+ src/tools/general.py,sha256=whj1spjIb8SS75h843X6c3RTsrZcSm-66KVLlY7OEh0,817
16
19
  src/tools/index.py,sha256=7KNPtElTFelkjRSvdMqPBx9nx_9Uk01OnTMeVo7YeCs,1345
17
20
  src/tools/register.py,sha256=wrG2P6-YPW77bTg1j_ELp8omWRYsJjFeOHUy_unHe6Y,1344
18
- opensearch_mcp_server-2.0.2.dist-info/METADATA,sha256=G1phXdISE1LdPqcw9087IDXr4YXLYuEsXuF2OHr8S-o,18514
19
- opensearch_mcp_server-2.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- opensearch_mcp_server-2.0.2.dist-info/entry_points.txt,sha256=ImfJnUwMpQUBmu-1MeBG_P0dwamfXKQh82mBKW7tWNY,138
21
- opensearch_mcp_server-2.0.2.dist-info/licenses/LICENSE,sha256=DBsjuP5FR51d9kaUdXlVBuBv3cQ_I_adq9gefYQ9FcY,11339
22
- opensearch_mcp_server-2.0.2.dist-info/RECORD,,
21
+ opensearch_mcp_server-2.0.4.dist-info/METADATA,sha256=L_fxn1Xf85fqRa4eRfxOct1WJCdnVZA3fDT9SwxUtdc,18688
22
+ opensearch_mcp_server-2.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ opensearch_mcp_server-2.0.4.dist-info/entry_points.txt,sha256=ImfJnUwMpQUBmu-1MeBG_P0dwamfXKQh82mBKW7tWNY,138
24
+ opensearch_mcp_server-2.0.4.dist-info/licenses/LICENSE,sha256=DBsjuP5FR51d9kaUdXlVBuBv3cQ_I_adq9gefYQ9FcY,11339
25
+ opensearch_mcp_server-2.0.4.dist-info/RECORD,,
src/clients/base.py CHANGED
@@ -3,6 +3,10 @@ import logging
3
3
  import warnings
4
4
  from typing import Dict
5
5
 
6
+ from elasticsearch import Elasticsearch
7
+ import httpx
8
+ from opensearchpy import OpenSearch
9
+
6
10
  class SearchClientBase(ABC):
7
11
  def __init__(self, config: Dict, engine_type: str):
8
12
  """
@@ -35,7 +39,6 @@ class SearchClientBase(ABC):
35
39
 
36
40
  # Initialize client based on engine type
37
41
  if engine_type == "elasticsearch":
38
- from elasticsearch import Elasticsearch
39
42
  self.client = Elasticsearch(
40
43
  hosts=hosts,
41
44
  basic_auth=(username, password) if username and password else None,
@@ -43,7 +46,6 @@ class SearchClientBase(ABC):
43
46
  )
44
47
  self.logger.info(f"Elasticsearch client initialized with hosts: {hosts}")
45
48
  elif engine_type == "opensearch":
46
- from opensearchpy import OpenSearch
47
49
  self.client = OpenSearch(
48
50
  hosts=hosts,
49
51
  http_auth=(username, password) if username and password else None,
@@ -52,3 +54,34 @@ class SearchClientBase(ABC):
52
54
  self.logger.info(f"OpenSearch client initialized with hosts: {hosts}")
53
55
  else:
54
56
  raise ValueError(f"Unsupported engine type: {engine_type}")
57
+
58
+ # General REST client
59
+ base_url = hosts[0] if isinstance(hosts, list) else hosts
60
+ self.general_client = GeneralRestClient(
61
+ base_url=base_url,
62
+ username=username,
63
+ password=password,
64
+ verify_certs=verify_certs,
65
+ )
66
+
67
+ class GeneralRestClient:
68
+ def __init__(self, base_url: str, username: str, password: str, verify_certs: bool):
69
+ self.base_url = base_url.rstrip("/")
70
+ self.auth = (username, password) if username and password else None
71
+ self.verify_certs = verify_certs
72
+
73
+ def request(self, method, path, params=None, body=None):
74
+ url = f"{self.base_url}/{path.lstrip('/')}"
75
+ with httpx.Client(verify=self.verify_certs) as client:
76
+ resp = client.request(
77
+ method=method.upper(),
78
+ url=url,
79
+ params=params,
80
+ json=body,
81
+ auth=self.auth
82
+ )
83
+ resp.raise_for_status()
84
+ ct = resp.headers.get("content-type", "")
85
+ if ct.startswith("application/json"):
86
+ return resp.json()
87
+ return resp.text
@@ -3,9 +3,10 @@ from typing import Dict
3
3
  from src.clients.common.alias import AliasClient
4
4
  from src.clients.common.cluster import ClusterClient
5
5
  from src.clients.common.document import DocumentClient
6
+ from src.clients.common.general import GeneralClient
6
7
  from src.clients.common.index import IndexClient
7
8
 
8
- class SearchClient(IndexClient, DocumentClient, ClusterClient, AliasClient):
9
+ class SearchClient(IndexClient, DocumentClient, ClusterClient, AliasClient, GeneralClient):
9
10
  """
10
11
  Unified search client that combines all search functionality.
11
12
 
@@ -0,0 +1,10 @@
1
+ from typing import Dict, Optional
2
+
3
+ from src.clients.base import SearchClientBase
4
+
5
+ class GeneralClient(SearchClientBase):
6
+ def general_api_request(self, method: str, path: str, params: Optional[Dict] = None, body: Optional[Dict] = None):
7
+ """Perform a general HTTP API request.
8
+ Use this tool for any Elasticsearch/OpenSearch API that does not have a dedicated tool.
9
+ """
10
+ return self.general_client.request(method, path, params, body)
src/server.py CHANGED
@@ -7,8 +7,10 @@ from src.clients import create_search_client
7
7
  from src.tools.alias import AliasTools
8
8
  from src.tools.cluster import ClusterTools
9
9
  from src.tools.document import DocumentTools
10
+ from src.tools.general import GeneralTools
10
11
  from src.tools.index import IndexTools
11
12
  from src.tools.register import ToolsRegister
13
+ from src.version import __version__ as VERSION
12
14
 
13
15
  class SearchMCPServer:
14
16
  def __init__(self, engine_type):
@@ -17,7 +19,7 @@ class SearchMCPServer:
17
19
  self.name = f"{self.engine_type}_mcp_server"
18
20
  self.mcp = FastMCP(self.name)
19
21
  self.logger = logging.getLogger()
20
- self.logger.info(f"Initializing {self.name}...")
22
+ self.logger.info(f"Initializing {self.name}, Version: {VERSION}")
21
23
 
22
24
  # Create the corresponding search client
23
25
  self.search_client = create_search_client(self.engine_type)
@@ -35,7 +37,8 @@ class SearchMCPServer:
35
37
  IndexTools,
36
38
  DocumentTools,
37
39
  ClusterTools,
38
- AliasTools
40
+ AliasTools,
41
+ GeneralTools,
39
42
  ]
40
43
  # Register all tools
41
44
  register.register_all_tools(tool_classes)
src/tools/__init__.py CHANGED
@@ -1,13 +1,15 @@
1
- from src.tools.index import IndexTools
2
- from src.tools.document import DocumentTools
3
- from src.tools.cluster import ClusterTools
4
1
  from src.tools.alias import AliasTools
2
+ from src.tools.cluster import ClusterTools
3
+ from src.tools.document import DocumentTools
4
+ from src.tools.general import GeneralTools
5
+ from src.tools.index import IndexTools
5
6
  from src.tools.register import ToolsRegister
6
7
 
7
8
  __all__ = [
8
- 'IndexTools',
9
- 'DocumentTools',
10
- 'ClusterTools',
11
9
  'AliasTools',
10
+ 'ClusterTools',
11
+ 'DocumentTools',
12
+ 'GeneralTools',
13
+ 'IndexTools',
12
14
  'ToolsRegister',
13
15
  ]
src/tools/general.py ADDED
@@ -0,0 +1,20 @@
1
+ from typing import Dict, Optional
2
+
3
+ from fastmcp import FastMCP
4
+
5
+ class GeneralTools:
6
+ def __init__(self, search_client):
7
+ self.search_client = search_client
8
+ def register_tools(self, mcp: FastMCP):
9
+ @mcp.tool()
10
+ def general_api_request(method: str, path: str, params: Optional[Dict] = None, body: Optional[Dict] = None):
11
+ """Perform a general HTTP API request.
12
+ Use this tool for any Elasticsearch/OpenSearch API that does not have a dedicated tool.
13
+
14
+ Args:
15
+ method: HTTP method (GET, POST, PUT, DELETE, etc.)
16
+ path: API endpoint path
17
+ params: Query parameters
18
+ body: Request body
19
+ """
20
+ return self.search_client.general_api_request(method, path, params, body)
src/version.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "2.0.4"