couchbase-mcp-server 0.4.0rc1__py3-none-any.whl → 0.5.1__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.
certs/__init__.py ADDED
File without changes
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDFTCCAf2gAwIBAgIRANLVkgOvtaXiQJi0V6qeNtswDQYJKoZIhvcNAQELBQAw
3
+ JDESMBAGA1UECgwJQ291Y2hiYXNlMQ4wDAYDVQQLDAVDbG91ZDAeFw0xOTEyMDYy
4
+ MjEyNTlaFw0yOTEyMDYyMzEyNTlaMCQxEjAQBgNVBAoMCUNvdWNoYmFzZTEOMAwG
5
+ A1UECwwFQ2xvdWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfvOIi
6
+ enG4Dp+hJu9asdxEMRmH70hDyMXv5ZjBhbo39a42QwR59y/rC/sahLLQuNwqif85
7
+ Fod1DkqgO6Ng3vecSAwyYVkj5NKdycQu5tzsZkghlpSDAyI0xlIPSQjoORA/pCOU
8
+ WOpymA9dOjC1bo6rDyw0yWP2nFAI/KA4Z806XeqLREuB7292UnSsgFs4/5lqeil6
9
+ rL3ooAw/i0uxr/TQSaxi1l8t4iMt4/gU+W52+8Yol0JbXBTFX6itg62ppb/Eugmn
10
+ mQRMgL67ccZs7cJ9/A0wlXencX2ohZQOR3mtknfol3FH4+glQFn27Q4xBCzVkY9j
11
+ KQ20T1LgmGSngBInAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
12
+ FJQOBPvrkU2In1Sjoxt97Xy8+cKNMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0B
13
+ AQsFAAOCAQEARgM6XwcXPLSpFdSf0w8PtpNGehmdWijPM3wHb7WZiS47iNen3oq8
14
+ m2mm6V3Z57wbboPpfI+VEzbhiDcFfVnK1CXMC0tkF3fnOG1BDDvwt4jU95vBiNjY
15
+ xdzlTP/Z+qr0cnVbGBSZ+fbXstSiRaaAVcqQyv3BRvBadKBkCyPwo+7svQnScQ5P
16
+ Js7HEHKVms5tZTgKIw1fbmgR2XHleah1AcANB+MAPBCcTgqurqr5G7W2aPSBLLGA
17
+ fRIiVzm7VFLc7kWbp7ENH39HVG6TZzKnfl9zJYeiklo5vQQhGSMhzBsO70z4RRzi
18
+ DPFAN/4qZAgD5q3AFNIq2WWADFQGSwVJhg==
19
+ -----END CERTIFICATE-----
@@ -1,32 +1,32 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: couchbase-mcp-server
3
- Version: 0.4.0rc1
3
+ Version: 0.5.1
4
4
  Summary: Couchbase MCP Server - The Developer Data Platform for Critical Applications in Our AI World
5
- Author-email: Nithish Raghunandanan <devadvocates@couchbase.com>
6
- License-Expression: Apache-2.0
7
5
  Project-URL: Homepage, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase
8
6
  Project-URL: Documentation, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase#readme
9
7
  Project-URL: Issues, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase/issues
8
+ Author-email: Nithish Raghunandanan <devadvocates@couchbase.com>
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
10
11
  Classifier: Development Status :: 4 - Beta
11
12
  Classifier: Programming Language :: Python :: 3
12
13
  Classifier: Topic :: Database
13
- Requires-Python: >=3.10
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
- Requires-Dist: click==8.2.1
17
- Requires-Dist: couchbase==4.4.0
18
- Requires-Dist: lark-sqlpp==0.0.1
19
- Requires-Dist: mcp[cli]==1.12.0
14
+ Requires-Python: <3.14,>=3.10
15
+ Requires-Dist: click<9.0.0,>=8.2.1
16
+ Requires-Dist: couchbase<5.0.0,>=4.4.0
17
+ Requires-Dist: lark-sqlpp>=0.0.1
18
+ Requires-Dist: mcp[cli]<2.0.0,>=1.20.0
19
+ Requires-Dist: urllib3>=2.0.0
20
20
  Provides-Extra: dev
21
- Requires-Dist: ruff==0.12.5; extra == "dev"
22
- Requires-Dist: pre-commit==4.2.0; extra == "dev"
23
- Dynamic: license-file
21
+ Requires-Dist: pre-commit==4.2.0; extra == 'dev'
22
+ Requires-Dist: ruff==0.12.5; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
24
 
25
25
  # Couchbase MCP Server
26
26
 
27
27
  An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase that allows LLMs to directly interact with Couchbase clusters.
28
28
 
29
- [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![PyPI version](https://badge.fury.io/py/couchbase-mcp-server.svg)](https://pypi.org/project/couchbase-mcp-server/) [![Verified on MseeP](https://mseep.ai/badge.svg)](https://mseep.ai/app/13fce476-0e74-4b1e-ab82-1df2a3204809)
29
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![PyPI version](https://badge.fury.io/py/couchbase-mcp-server.svg)](https://pypi.org/project/couchbase-mcp-server/) [![Verified on MseeP](https://mseep.ai/badge.svg)](https://mseep.ai/app/13fce476-0e74-4b1e-ab82-1df2a3204809) [![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/Couchbase-Ecosystem/mcp-server-couchbase)](https://archestra.ai/mcp-catalog/couchbase-ecosystem__mcp-server-couchbase)
30
30
 
31
31
  <a href="https://glama.ai/mcp/servers/@Couchbase-Ecosystem/mcp-server-couchbase">
32
32
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@Couchbase-Ecosystem/mcp-server-couchbase/badge" alt="Couchbase Server MCP server" />
@@ -34,7 +34,10 @@ An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase th
34
34
 
35
35
  ## Features
36
36
 
37
+ - Get a list of all the buckets in the cluster
37
38
  - Get a list of all the scopes and collections in the specified bucket
39
+ - Get a list of all the scopes in the specified bucket
40
+ - Get a list of all the collections in a specified scope and bucket. Note that this tool requires the cluster to have Query service.
38
41
  - Get the structure for a collection
39
42
  - Get a document by ID from a specified scope and collection
40
43
  - Upsert a document by ID to a specified scope and collection
@@ -43,6 +46,9 @@ An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase th
43
46
  - There is an option in the MCP server, `CB_MCP_READ_ONLY_QUERY_MODE` that is set to true by default to disable running SQL++ queries that change the data or the underlying collection structure. Note that the documents can still be updated by ID.
44
47
  - Get the status of the MCP server
45
48
  - Check the cluster credentials by connecting to the cluster
49
+ - List all indexes in the cluster with their definitions, with optional filtering by bucket, scope, collection and index name.
50
+ - Get index recommendations from Couchbase Index Advisor for a given SQL++ query to optimize query performance
51
+ - Get cluster health status and list of all running services
46
52
 
47
53
  ## Prerequisites
48
54
 
@@ -53,7 +59,7 @@ An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase th
53
59
 
54
60
  ## Configuration
55
61
 
56
- The MCP server can be run either from the pre built PyPI package or the source using uv.
62
+ The MCP server can be run either from the prebuilt PyPI package or the source using uv.
57
63
 
58
64
  ### Running from PyPI
59
65
 
@@ -61,6 +67,8 @@ We publish a pre built [PyPI package](https://pypi.org/project/couchbase-mcp-ser
61
67
 
62
68
  #### Server Configuration using Pre built Package for MCP Clients
63
69
 
70
+ #### Basic Authentication
71
+
64
72
  ```json
65
73
  {
66
74
  "mcpServers": {
@@ -70,8 +78,27 @@ We publish a pre built [PyPI package](https://pypi.org/project/couchbase-mcp-ser
70
78
  "env": {
71
79
  "CB_CONNECTION_STRING": "couchbases://connection-string",
72
80
  "CB_USERNAME": "username",
73
- "CB_PASSWORD": "password",
74
- "CB_BUCKET_NAME": "bucket_name"
81
+ "CB_PASSWORD": "password"
82
+ }
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ or
89
+
90
+ #### mTLS
91
+
92
+ ```json
93
+ {
94
+ "mcpServers": {
95
+ "couchbase": {
96
+ "command": "uvx",
97
+ "args": ["couchbase-mcp-server"],
98
+ "env": {
99
+ "CB_CONNECTION_STRING": "couchbases://connection-string",
100
+ "CB_CLIENT_CERT_PATH": "/path/to/client-certificate.pem",
101
+ "CB_CLIENT_KEY_PATH": "/path/to/client.key"
75
102
  }
76
103
  }
77
104
  }
@@ -108,8 +135,7 @@ This is the common configuration for the MCP clients such as Claude Desktop, Cur
108
135
  "env": {
109
136
  "CB_CONNECTION_STRING": "couchbases://connection-string",
110
137
  "CB_USERNAME": "username",
111
- "CB_PASSWORD": "password",
112
- "CB_BUCKET_NAME": "bucket_name"
138
+ "CB_PASSWORD": "password"
113
139
  }
114
140
  }
115
141
  }
@@ -123,17 +149,21 @@ This is the common configuration for the MCP clients such as Claude Desktop, Cur
123
149
  ### Additional Configuration for MCP Server
124
150
 
125
151
  The server can be configured using environment variables or command line arguments:
126
-
127
- | Environment Variable | CLI Argument | Description | Default |
128
- | ----------------------------- | ------------------------ | ------------------------------------------ | ------------ |
129
- | `CB_CONNECTION_STRING` | `--connection-string` | Connection string to the Couchbase cluster | **Required** |
130
- | `CB_USERNAME` | `--username` | Username with bucket access | **Required** |
131
- | `CB_PASSWORD` | `--password` | Password for authentication | **Required** |
132
- | `CB_BUCKET_NAME` | `--bucket-name` | Name of the bucket to access | **Required** |
133
- | `CB_MCP_READ_ONLY_QUERY_MODE` | `--read-only-query-mode` | Prevent data modification queries | `true` |
134
- | `CB_MCP_TRANSPORT` | `--transport` | Transport mode: `stdio`, `http`, `sse` | `stdio` |
135
- | `CB_MCP_HOST` | `--host` | Host for HTTP/SSE transport modes | `127.0.0.1` |
136
- | `CB_MCP_PORT` | `--port` | Port for HTTP/SSE transport modes | `8000` |
152
+ | Environment Variable | CLI Argument | Description | Default |
153
+ |--------------------------------|--------------------------|---------------------------------------------------------------------------------------------|------------------------------------------|
154
+ | `CB_CONNECTION_STRING` | `--connection-string` | Connection string to the Couchbase cluster | **Required** |
155
+ | `CB_USERNAME` | `--username` | Username with access to required buckets for basic authentication | **Required (or Client Certificate and Key needed for mTLS)** |
156
+ | `CB_PASSWORD` | `--password` | Password for basic authentication | **Required (or Client Certificate and Key needed for mTLS)** |
157
+ | `CB_CLIENT_CERT_PATH` | `--client-cert-path` | Path to the client certificate file for mTLS authentication| **Required if using mTLS (or Username and Password required)** |
158
+ | `CB_CLIENT_KEY_PATH` | `--client-key-path` | Path to the client key file for mTLS authentication| **Required if using mTLS (or Username and Password required)** |
159
+ | `CB_CA_CERT_PATH` | `--ca-cert-path` | Path to server root certificate for TLS if server is configured with a self-signed/untrusted certificate. This will not be required if you are connecting to Capella | |
160
+ | `CB_MCP_READ_ONLY_QUERY_MODE` | `--read-only-query-mode` | Prevent data modification queries | `true` |
161
+ | `CB_MCP_TRANSPORT` | `--transport` | Transport mode: `stdio`, `http`, `sse` | `stdio` |
162
+ | `CB_MCP_HOST` | `--host` | Host for HTTP/SSE transport modes | `127.0.0.1` |
163
+ | `CB_MCP_PORT` | `--port` | Port for HTTP/SSE transport modes | `8000` |
164
+
165
+ > Note: For authentication, you need either the Username and Password or the Client Certificate and key paths. Optionally, you can specify the CA root certificate path that will be used to validate the server certificates.
166
+ > If both the Client Certificate & key path and the username and password are specified, the client certificates will be used for authentication.
137
167
 
138
168
  You can also check the version of the server using:
139
169
 
@@ -228,7 +258,12 @@ Check if your [MCP client](https://modelcontextprotocol.io/clients) supports str
228
258
  By default, the MCP server will run on port 8000 but this can be configured using the `--port` or `CB_MCP_PORT` environment variable.
229
259
 
230
260
  ```bash
231
- uvx couchbase-mcp-server --connection-string='<couchbase_connection_string>' --username='<database_username>' --password='<database_password>' --bucket-name='<couchbase_bucket_to_use>' --read-only-query-mode=true --transport=streamable-http
261
+ uvx couchbase-mcp-server \
262
+ --connection-string='<couchbase_connection_string>' \
263
+ --username='<database_username>' \
264
+ --password='<database_password>' \
265
+ --read-only-query-mode=true \
266
+ --transport=http
232
267
  ```
233
268
 
234
269
  The server will be available on http://localhost:8000/mcp. This can be used in MCP clients supporting streamable http transport mode such as Cursor.
@@ -256,7 +291,12 @@ There is an option to run the MCP server in [Server-Sent Events (SSE)](https://m
256
291
  By default, the MCP server will run on port 8000 but this can be configured using the `--port` or `CB_MCP_PORT` environment variable.
257
292
 
258
293
  ```bash
259
- uvx couchbase-mcp-server --connection-string='<couchbase_connection_string>' --username='<database_username>' --password='<database_password>' --bucket-name='<couchbase_bucket_to_use>' --read-only-query-mode=true --transport=sse
294
+ uvx couchbase-mcp-server \
295
+ --connection-string='<couchbase_connection_string>' \
296
+ --username='<database_username>' \
297
+ --password='<database_password>' \
298
+ --read-only-query-mode=true \
299
+ --transport=sse
260
300
  ```
261
301
 
262
302
  The server will be available on http://localhost:8000/sse. This can be used in MCP clients supporting SSE transport mode such as Cursor.
@@ -331,7 +371,6 @@ docker run --rm -i \
331
371
  -e CB_CONNECTION_STRING='<couchbase_connection_string>' \
332
372
  -e CB_USERNAME='<database_user>' \
333
373
  -e CB_PASSWORD='<database_password>' \
334
- -e CB_BUCKET_NAME='<bucket_name>' \
335
374
  -e CB_MCP_TRANSPORT='<http|sse|stdio>' \
336
375
  -e CB_MCP_READ_ONLY_QUERY_MODE='<true|false>' \
337
376
  -e CB_MCP_PORT=9001 \
@@ -360,8 +399,6 @@ The Docker image can be used in `stdio` transport mode with the following config
360
399
  "CB_USERNAME=<database_user>",
361
400
  "-e",
362
401
  "CB_PASSWORD=<database_password>",
363
- "-e",
364
- "CB_BUCKET_NAME=<bucket_name>",
365
402
  "mcp/couchbase"
366
403
  ]
367
404
  }
@@ -387,11 +424,11 @@ The Couchbase MCP server can also be used as a managed server in your agentic ap
387
424
  ## Troubleshooting Tips
388
425
 
389
426
  - Ensure the path to your MCP server repository is correct in the configuration if running from source.
390
- - Verify that your Couchbase connection string, database username, password and bucket name are correct.
427
+ - Verify that your Couchbase connection string, database username, password or the path to the certificates are correct.
391
428
  - If using Couchbase Capella, ensure that the cluster is [accessible](https://docs.couchbase.com/cloud/clusters/allow-ip-address.html) from the machine where the MCP server is running.
392
- - Check that the database user has proper permissions to access the specified bucket.
393
- - Confirm that the uv package manager is properly installed and accessible. You may need to provide absolute path to uv/uvx in the `command` field in the configuration.
394
- - Check the logs for any errors or warnings that may indicate issues with the MCP server. The server logs are under the name, `mcp-server-couchbase.log`.
429
+ - Check that the database user has proper permissions to access at least one bucket.
430
+ - Confirm that the `uv` package manager is properly installed and accessible. You may need to provide absolute path to `uv`/`uvx` in the `command` field in the configuration.
431
+ - Check the logs for any errors or warnings that may indicate issues with the MCP server. The location of the logs depend on your MCP client.
395
432
  - If you are observing issues running your MCP server from source after updating your local MCP server repository, try running `uv sync` to update the [dependencies](https://docs.astral.sh/uv/concepts/projects/sync/#syncing-the-environment).
396
433
 
397
434
  ---
@@ -0,0 +1,19 @@
1
+ certs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ certs/capella_root_ca.pem,sha256=SuSjgKclcQQg0kheTRd3dg6B0FUsUy717T5n3xcAU_E,1131
3
+ mcp_server.py,sha256=dvHQR-55JhuXX_bj2hLU0ek411qPp0qHEKqAmPdwjKU,4991
4
+ tools/__init__.py,sha256=otQd8IiEILtl1jgorEO1E9KqL_2xBBlqwnVHejoCPE0,1668
5
+ tools/index.py,sha256=cCBr0ptFBVc-HN5SoCauQAh2DsAP_Is8NPUSa6QcLM0,6682
6
+ tools/kv.py,sha256=NGUs43iuXElj9rYe4RCyCStqoh5y1fUgbg1oWuU4WeQ,2493
7
+ tools/query.py,sha256=fSSG7XuxnND1lHwI-r8y_M3h6f82vCXxCwB_A2wHN-M,3598
8
+ tools/server.py,sha256=4krPjBoQmUHUmOE03T0CcCGFJtoaeHVS91oOrYj8JsA,6670
9
+ utils/__init__.py,sha256=Fcbp-VIK0Gwwy7hl1AjV9NBKZsscmOV2vYdTBam5M3A,1361
10
+ utils/config.py,sha256=B6H_JYDn6uxtu9juM924zdvNQgSaHh_u6rYME3_0_xQ,268
11
+ utils/connection.py,sha256=NtAU4pmHMZubSJcs_X_lai9o8dih5mW0RyrRdmyp1Po,2892
12
+ utils/constants.py,sha256=w0zvQ1zMzJBg44Yl3aQW8KfaaRPn0BgPOLEe8xLeLSE,487
13
+ utils/context.py,sha256=XZL4M70BMdFBptJ9sT0zxhEey-EvvoSKZJrP_sb7q-A,2286
14
+ utils/index_utils.py,sha256=W0rvoBXU_2aB9m-HDlLChZoMzvlIX6FUWF6RTsYGfYM,10910
15
+ couchbase_mcp_server-0.5.1.dist-info/METADATA,sha256=ufeqvKJPZcWL_b0uki8UqGMuU34c2R2--aNnP1211MY,20964
16
+ couchbase_mcp_server-0.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ couchbase_mcp_server-0.5.1.dist-info/entry_points.txt,sha256=iU5pF4kIMTnNhoMPHhdH-k8o1Fmxb_iM9qJHCZcL6Ak,57
18
+ couchbase_mcp_server-0.5.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
19
+ couchbase_mcp_server-0.5.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
mcp_server.py CHANGED
@@ -78,9 +78,22 @@ async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
78
78
  help="Couchbase database password (required for operations)",
79
79
  )
80
80
  @click.option(
81
- "--bucket-name",
82
- envvar="CB_BUCKET_NAME",
83
- help="Couchbase bucket name (required for operations)",
81
+ "--ca-cert-path",
82
+ envvar="CB_CA_CERT_PATH",
83
+ default=None,
84
+ help="Path to the server trust store (CA certificate) file. The certificate at this path is used to verify the server certificate during the authentication process.",
85
+ )
86
+ @click.option(
87
+ "--client-cert-path",
88
+ envvar="CB_CLIENT_CERT_PATH",
89
+ default=None,
90
+ help="Path to the client certificate file used for mTLS authentication.",
91
+ )
92
+ @click.option(
93
+ "--client-key-path",
94
+ envvar="CB_CLIENT_KEY_PATH",
95
+ default=None,
96
+ help="Path to the client certificate key file used for mTLS authentication.",
84
97
  )
85
98
  @click.option(
86
99
  "--read-only-query-mode",
@@ -121,7 +134,9 @@ def main(
121
134
  connection_string,
122
135
  username,
123
136
  password,
124
- bucket_name,
137
+ ca_cert_path,
138
+ client_cert_path,
139
+ client_key_path,
125
140
  read_only_query_mode,
126
141
  transport,
127
142
  host,
@@ -133,7 +148,9 @@ def main(
133
148
  "connection_string": connection_string,
134
149
  "username": username,
135
150
  "password": password,
136
- "bucket_name": bucket_name,
151
+ "ca_cert_path": ca_cert_path,
152
+ "client_cert_path": client_cert_path,
153
+ "client_key_path": client_key_path,
137
154
  "read_only_query_mode": read_only_query_mode,
138
155
  "transport": transport,
139
156
  "host": host,
@@ -148,7 +165,6 @@ def main(
148
165
  {
149
166
  "host": host,
150
167
  "port": port,
151
- "transport": sdk_transport,
152
168
  }
153
169
  if transport in NETWORK_TRANSPORTS
154
170
  else {}
tools/__init__.py CHANGED
@@ -4,6 +4,9 @@ Couchbase MCP Tools
4
4
  This module contains all the MCP tools for Couchbase operations.
5
5
  """
6
6
 
7
+ # Index tools
8
+ from .index import get_index_advisor_recommendations, list_indexes
9
+
7
10
  # Key-Value tools
8
11
  from .kv import (
9
12
  delete_document_by_id,
@@ -19,21 +22,31 @@ from .query import (
19
22
 
20
23
  # Server tools
21
24
  from .server import (
25
+ get_buckets_in_cluster,
26
+ get_cluster_health_and_services,
27
+ get_collections_in_scope,
22
28
  get_scopes_and_collections_in_bucket,
29
+ get_scopes_in_bucket,
23
30
  get_server_configuration_status,
24
31
  test_cluster_connection,
25
32
  )
26
33
 
27
34
  # List of all tools for easy registration
28
35
  ALL_TOOLS = [
36
+ get_buckets_in_cluster,
29
37
  get_server_configuration_status,
30
38
  test_cluster_connection,
31
39
  get_scopes_and_collections_in_bucket,
40
+ get_collections_in_scope,
41
+ get_scopes_in_bucket,
32
42
  get_document_by_id,
33
43
  upsert_document_by_id,
34
44
  delete_document_by_id,
35
45
  get_schema_for_collection,
36
46
  run_sql_plus_plus_query,
47
+ get_index_advisor_recommendations,
48
+ list_indexes,
49
+ get_cluster_health_and_services,
37
50
  ]
38
51
 
39
52
  __all__ = [
@@ -41,11 +54,17 @@ __all__ = [
41
54
  "get_server_configuration_status",
42
55
  "test_cluster_connection",
43
56
  "get_scopes_and_collections_in_bucket",
57
+ "get_collections_in_scope",
58
+ "get_scopes_in_bucket",
59
+ "get_buckets_in_cluster",
44
60
  "get_document_by_id",
45
61
  "upsert_document_by_id",
46
62
  "delete_document_by_id",
47
63
  "get_schema_for_collection",
48
64
  "run_sql_plus_plus_query",
65
+ "get_index_advisor_recommendations",
66
+ "list_indexes",
67
+ "get_cluster_health_and_services",
49
68
  # Convenience
50
69
  "ALL_TOOLS",
51
70
  ]
tools/index.py ADDED
@@ -0,0 +1,172 @@
1
+ """
2
+ Tools for index operations.
3
+
4
+ This module contains tools for listing and managing indexes in the Couchbase cluster and getting index recommendations using the Couchbase Index Advisor.
5
+ """
6
+
7
+ import logging
8
+ from typing import Any
9
+
10
+ from mcp.server.fastmcp import Context
11
+
12
+ from tools.query import run_sql_plus_plus_query
13
+ from utils.config import get_settings
14
+ from utils.constants import MCP_SERVER_NAME
15
+ from utils.index_utils import (
16
+ fetch_indexes_from_rest_api,
17
+ process_index_data,
18
+ validate_connection_settings,
19
+ validate_filter_params,
20
+ )
21
+
22
+ logger = logging.getLogger(f"{MCP_SERVER_NAME}.tools.index")
23
+
24
+
25
+ def get_index_advisor_recommendations(
26
+ ctx: Context, bucket_name: str, scope_name: str, query: str
27
+ ) -> dict[str, Any]:
28
+ """Get index recommendations from Couchbase Index Advisor for a given SQL++ query.
29
+
30
+ The Index Advisor analyzes the query and provides recommendations for optimal indexes.
31
+ This tool works with SELECT, UPDATE, DELETE, or MERGE queries.
32
+ The queries will be run on the specified scope in the specified bucket.
33
+
34
+ Returns a dictionary with:
35
+ - current_used_indexes: Array of currently used indexes (if any)
36
+ - recommended_indexes: Array of recommended secondary indexes (if any)
37
+ - recommended_covering_indexes: Array of recommended covering indexes (if any)
38
+
39
+ Each index object contains:
40
+ - index: The CREATE INDEX SQL++ command
41
+ - statements: Array of statement objects with the query and run count
42
+ """
43
+ try:
44
+ # Build the ADVISOR query
45
+ advisor_query = f"SELECT ADVISOR('{query}') AS advisor_result"
46
+
47
+ logger.info("Running Index Advisor for the provided query")
48
+
49
+ # Execute the ADVISOR function at cluster level using run_sql_plus_plus_query
50
+ advisor_results = run_sql_plus_plus_query(
51
+ ctx, bucket_name, scope_name, advisor_query
52
+ )
53
+
54
+ if not advisor_results:
55
+ return {
56
+ "message": "No recommendations available",
57
+ "current_used_indexes": [],
58
+ "recommended_indexes": [],
59
+ "recommended_covering_indexes": [],
60
+ }
61
+
62
+ # The result is wrapped in advisor_result key
63
+ advisor_data = advisor_results[0].get("advisor_result", {})
64
+
65
+ # Extract the relevant fields with defaults
66
+ response = {
67
+ "current_used_indexes": advisor_data.get("current_used_indexes", []),
68
+ "recommended_indexes": advisor_data.get("recommended_indexes", []),
69
+ "recommended_covering_indexes": advisor_data.get(
70
+ "recommended_covering_indexes", []
71
+ ),
72
+ }
73
+
74
+ # Add summary information for better user experience
75
+ response["summary"] = {
76
+ "current_indexes_count": len(response["current_used_indexes"]),
77
+ "recommended_indexes_count": len(response["recommended_indexes"]),
78
+ "recommended_covering_indexes_count": len(
79
+ response["recommended_covering_indexes"]
80
+ ),
81
+ "has_recommendations": bool(
82
+ response["recommended_indexes"]
83
+ or response["recommended_covering_indexes"]
84
+ ),
85
+ }
86
+
87
+ logger.info(
88
+ f"Index Advisor completed. Found {response['summary']['recommended_indexes_count']} recommended indexes"
89
+ )
90
+
91
+ return response
92
+
93
+ except Exception as e:
94
+ logger.error(f"Error running Index Advisor: {e!s}", exc_info=True)
95
+ raise
96
+
97
+
98
+ def list_indexes(
99
+ ctx: Context,
100
+ bucket_name: str | None = None,
101
+ scope_name: str | None = None,
102
+ collection_name: str | None = None,
103
+ index_name: str | None = None,
104
+ include_raw_index_stats: bool = False,
105
+ ) -> list[dict[str, Any]]:
106
+ """List all indexes in the cluster with optional filtering by bucket, scope, collection, and index name.
107
+ Returns a list of indexes with their names and CREATE INDEX definitions.
108
+ Uses the Index Service REST API (/getIndexStatus) to retrieve index information directly.
109
+
110
+ Args:
111
+ ctx: MCP context for cluster connection
112
+ bucket_name: Optional bucket name to filter indexes
113
+ scope_name: Optional scope name to filter indexes (requires bucket_name)
114
+ collection_name: Optional collection name to filter indexes (requires bucket_name and scope_name)
115
+ index_name: Optional index name to filter indexes (requires bucket_name, scope_name, and collection_name)
116
+ include_raw_index_stats: If True, include raw index stats (as-is from API) in addition
117
+ to cleaned-up version. Default is False.
118
+
119
+ Returns:
120
+ List of dictionaries with keys:
121
+ - name (str): Index name
122
+ - definition (str): Cleaned-up CREATE INDEX statement
123
+ - status (str): Current status of the index (e.g., "Ready", "Building", "Deferred")
124
+ - isPrimary (bool): Whether this is a primary index
125
+ - bucket (str): Bucket name where the index exists
126
+ - scope (str): Scope name where the index exists
127
+ - collection (str): Collection name where the index exists
128
+ - raw_index_stats (dict, optional): Complete raw index status object from API including metadata,
129
+ state, keyspace info, etc. (only if include_raw_index_stats=True)
130
+ """
131
+ try:
132
+ # Validate parameters
133
+ validate_filter_params(bucket_name, scope_name, collection_name, index_name)
134
+
135
+ # Get and validate connection settings
136
+ settings = get_settings()
137
+ validate_connection_settings(settings)
138
+
139
+ # Fetch indexes from REST API
140
+ logger.info(
141
+ f"Fetching indexes from REST API for bucket={bucket_name}, "
142
+ f"scope={scope_name}, collection={collection_name}, index={index_name}"
143
+ )
144
+
145
+ raw_indexes = fetch_indexes_from_rest_api(
146
+ settings["connection_string"],
147
+ settings["username"],
148
+ settings["password"],
149
+ bucket_name=bucket_name,
150
+ scope_name=scope_name,
151
+ collection_name=collection_name,
152
+ index_name=index_name,
153
+ ca_cert_path=settings.get("ca_cert_path"),
154
+ )
155
+
156
+ # Process and format the results
157
+ indexes = [
158
+ processed
159
+ for idx in raw_indexes
160
+ if (processed := process_index_data(idx, include_raw_index_stats))
161
+ is not None
162
+ ]
163
+
164
+ logger.info(
165
+ f"Found {len(indexes)} indexes from REST API "
166
+ f"(include_raw_index_stats={include_raw_index_stats})"
167
+ )
168
+ return indexes
169
+
170
+ except Exception as e:
171
+ logger.error(f"Error listing indexes: {e}", exc_info=True)
172
+ raise
tools/kv.py CHANGED
@@ -9,18 +9,25 @@ from typing import Any
9
9
 
10
10
  from mcp.server.fastmcp import Context
11
11
 
12
+ from utils.connection import connect_to_bucket
12
13
  from utils.constants import MCP_SERVER_NAME
13
- from utils.context import ensure_bucket_connection
14
+ from utils.context import get_cluster_connection
14
15
 
15
16
  logger = logging.getLogger(f"{MCP_SERVER_NAME}.tools.kv")
16
17
 
17
18
 
18
19
  def get_document_by_id(
19
- ctx: Context, scope_name: str, collection_name: str, document_id: str
20
+ ctx: Context,
21
+ bucket_name: str,
22
+ scope_name: str,
23
+ collection_name: str,
24
+ document_id: str,
20
25
  ) -> dict[str, Any]:
21
26
  """Get a document by its ID from the specified scope and collection.
22
27
  If the document is not found, it will raise an exception."""
23
- bucket = ensure_bucket_connection(ctx)
28
+
29
+ cluster = get_cluster_connection(ctx)
30
+ bucket = connect_to_bucket(cluster, bucket_name)
24
31
  try:
25
32
  collection = bucket.scope(scope_name).collection(collection_name)
26
33
  result = collection.get(document_id)
@@ -32,6 +39,7 @@ def get_document_by_id(
32
39
 
33
40
  def upsert_document_by_id(
34
41
  ctx: Context,
42
+ bucket_name: str,
35
43
  scope_name: str,
36
44
  collection_name: str,
37
45
  document_id: str,
@@ -39,7 +47,8 @@ def upsert_document_by_id(
39
47
  ) -> bool:
40
48
  """Insert or update a document by its ID.
41
49
  Returns True on success, False on failure."""
42
- bucket = ensure_bucket_connection(ctx)
50
+ cluster = get_cluster_connection(ctx)
51
+ bucket = connect_to_bucket(cluster, bucket_name)
43
52
  try:
44
53
  collection = bucket.scope(scope_name).collection(collection_name)
45
54
  collection.upsert(document_id, document_content)
@@ -51,11 +60,16 @@ def upsert_document_by_id(
51
60
 
52
61
 
53
62
  def delete_document_by_id(
54
- ctx: Context, scope_name: str, collection_name: str, document_id: str
63
+ ctx: Context,
64
+ bucket_name: str,
65
+ scope_name: str,
66
+ collection_name: str,
67
+ document_id: str,
55
68
  ) -> bool:
56
69
  """Delete a document by its ID.
57
70
  Returns True on success, False on failure."""
58
- bucket = ensure_bucket_connection(ctx)
71
+ cluster = get_cluster_connection(ctx)
72
+ bucket = connect_to_bucket(cluster, bucket_name)
59
73
  try:
60
74
  collection = bucket.scope(scope_name).collection(collection_name)
61
75
  collection.remove(document_id)