couchbase-mcp-server 0.5.2rc5__tar.gz → 0.5.3__tar.gz

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.
Files changed (47) hide show
  1. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.github/workflows/docker.yml +12 -5
  2. couchbase_mcp_server-0.5.3/.github/workflows/test.yml +285 -0
  3. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.github/workflows/update-mcp-registry.yml +5 -3
  4. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/DOCKER.md +9 -0
  5. couchbase_mcp_server-0.5.2rc5/README.md → couchbase_mcp_server-0.5.3/PKG-INFO +50 -0
  6. couchbase_mcp_server-0.5.2rc5/PKG-INFO → couchbase_mcp_server-0.5.3/README.md +24 -24
  7. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/pyproject.toml +8 -1
  8. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/server.json +3 -3
  9. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/tools/__init__.py +21 -0
  10. couchbase_mcp_server-0.5.3/src/tools/query.py +360 -0
  11. couchbase_mcp_server-0.5.3/tests/conftest.py +234 -0
  12. couchbase_mcp_server-0.5.3/tests/test_index_tools.py +209 -0
  13. couchbase_mcp_server-0.5.3/tests/test_kv_tools.py +217 -0
  14. couchbase_mcp_server-0.5.3/tests/test_mcp_integration.py +262 -0
  15. couchbase_mcp_server-0.5.3/tests/test_performance_tools.py +291 -0
  16. couchbase_mcp_server-0.5.3/tests/test_query_tools.py +156 -0
  17. couchbase_mcp_server-0.5.3/tests/test_server_tools.py +137 -0
  18. couchbase_mcp_server-0.5.3/tests/test_utils.py +556 -0
  19. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/uv.lock +94 -1
  20. couchbase_mcp_server-0.5.2rc5/src/tools/query.py +0 -98
  21. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.github/workflows/alert-on-pr.yml +0 -0
  22. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.github/workflows/release.yml +0 -0
  23. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.github/workflows/test_release.yml +0 -0
  24. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.gitignore +0 -0
  25. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/.pre-commit-config.yaml +0 -0
  26. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/CONTRIBUTING.md +0 -0
  27. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/Dockerfile +0 -0
  28. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/LICENSE +0 -0
  29. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/RELEASE.md +0 -0
  30. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/build.sh +0 -0
  31. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/glama.json +0 -0
  32. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/scripts/lint.sh +0 -0
  33. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/scripts/lint_fix.sh +0 -0
  34. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/scripts/update_version.sh +0 -0
  35. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/smithery.yaml +0 -0
  36. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/certs/__init__.py +0 -0
  37. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/certs/capella_root_ca.pem +0 -0
  38. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/mcp_server.py +0 -0
  39. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/tools/index.py +0 -0
  40. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/tools/kv.py +0 -0
  41. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/tools/server.py +0 -0
  42. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/utils/__init__.py +0 -0
  43. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/utils/config.py +0 -0
  44. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/utils/connection.py +0 -0
  45. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/utils/constants.py +0 -0
  46. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/utils/context.py +0 -0
  47. {couchbase_mcp_server-0.5.2rc5 → couchbase_mcp_server-0.5.3}/src/utils/index_utils.py +0 -0
@@ -34,14 +34,18 @@ jobs:
34
34
 
35
35
  - name: Check if stable release
36
36
  id: check-stable
37
+ if: startsWith(github.ref, 'refs/tags/')
37
38
  run: |
38
39
  TAG_NAME="${GITHUB_REF#refs/tags/}"
40
+ echo "Checking tag: $TAG_NAME"
41
+
42
+ # Only match vX.Y.Z format (no suffixes like rc, alpha, beta)
39
43
  if [[ "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
40
44
  echo "is_stable=true" >> $GITHUB_OUTPUT
41
- echo "This is a stable release: $TAG_NAME"
45
+ echo "This is a STABLE release: $TAG_NAME"
42
46
  else
43
47
  echo "is_stable=false" >> $GITHUB_OUTPUT
44
- echo "This is a pre-release: $TAG_NAME"
48
+ echo "This is a PRE-RELEASE: $TAG_NAME (will not update 'latest' or major.minor tags)"
45
49
  fi
46
50
 
47
51
  - name: Extract metadata
@@ -49,14 +53,17 @@ jobs:
49
53
  uses: docker/metadata-action@v5
50
54
  with:
51
55
  images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
56
+ flavor: |
57
+ # Disable automatic 'latest' tag to have explicit control
58
+ latest=false
52
59
  tags: |
53
60
  # For PRs: tag as pr-<number>
54
61
  type=ref,event=pr
55
- # For tags: extract full version without 'v' prefix (e.g., 0.5.2 or 0.5.2rc3)
56
- type=match,pattern=v(.*),group=1,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
62
+ # For all tags: extract full version without 'v' prefix (e.g., 0.5.2 or 0.5.2rc3)
63
+ type=match,pattern=v(.*),group=1
57
64
  # For stable releases only: extract major.minor (e.g., 0.5 from v0.5.2)
58
65
  type=match,pattern=v(\d+\.\d+),group=1,enable=${{ steps.check-stable.outputs.is_stable == 'true' }}
59
- # Tag as 'latest' only for stable releases
66
+ # For stable releases only: tag as 'latest'
60
67
  type=raw,value=latest,enable=${{ steps.check-stable.outputs.is_stable == 'true' }}
61
68
 
62
69
  - name: Set build timestamp
@@ -0,0 +1,285 @@
1
+ name: Tests
2
+
3
+ permissions:
4
+ contents: read
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+ branches: [main]
11
+
12
+ env:
13
+ # Default test credentials for Couchbase
14
+ CB_USERNAME: Administrator
15
+ CB_PASSWORD: password
16
+ CB_MCP_TEST_BUCKET: travel-sample
17
+
18
+ jobs:
19
+ # ============================================
20
+ # Integration Tests - All Transport Modes
21
+ # ============================================
22
+ integration-tests:
23
+ name: Integration (${{ matrix.transport }} transport)
24
+ runs-on: ubuntu-latest
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ transport: ["stdio", "http", "sse"]
29
+
30
+ services:
31
+ couchbase:
32
+ image: couchbase:enterprise-8.0.0
33
+ ports:
34
+ - 8091:8091
35
+ - 8092:8092
36
+ - 8093:8093
37
+ - 8094:8094
38
+ - 8095:8095
39
+ - 8096:8096
40
+ - 9102:9102
41
+ - 11210:11210
42
+ - 11207:11207
43
+ options: >-
44
+ --health-cmd "curl -s http://localhost:8091/pools || exit 1"
45
+ --health-interval 10s
46
+ --health-timeout 5s
47
+ --health-retries 30
48
+
49
+ steps:
50
+ - name: Checkout code
51
+ uses: actions/checkout@v4
52
+
53
+ - name: Install uv
54
+ uses: astral-sh/setup-uv@v4
55
+ with:
56
+ version: "latest"
57
+
58
+ - name: Set up Python (latest)
59
+ run: uv python install 3.13
60
+
61
+ - name: Install dependencies
62
+ run: uv sync --extra dev
63
+
64
+ - name: Wait for Couchbase to be ready
65
+ run: |
66
+ echo "Waiting for Couchbase to be fully ready..."
67
+ for i in {1..60}; do
68
+ if curl -s http://localhost:8091/pools > /dev/null 2>&1; then
69
+ echo "Couchbase REST API is responding"
70
+ break
71
+ fi
72
+ echo "Waiting for Couchbase... ($i/60)"
73
+ sleep 2
74
+ done
75
+
76
+ - name: Initialize Couchbase cluster
77
+ run: |
78
+ echo "Initializing Couchbase cluster..."
79
+
80
+ # Initialize node
81
+ curl -s -X POST http://localhost:8091/nodes/self/controller/settings \
82
+ -d 'path=/opt/couchbase/var/lib/couchbase/data' \
83
+ -d 'index_path=/opt/couchbase/var/lib/couchbase/data'
84
+
85
+ # Set up services
86
+ curl -s -X POST http://localhost:8091/node/controller/setupServices \
87
+ -d 'services=kv,n1ql,index,fts'
88
+
89
+ # Set memory quotas
90
+ curl -s -X POST http://localhost:8091/pools/default \
91
+ -d 'memoryQuota=512' \
92
+ -d 'indexMemoryQuota=256' \
93
+ -d 'ftsMemoryQuota=256'
94
+
95
+ # Set credentials
96
+ curl -s -X POST http://localhost:8091/settings/web \
97
+ -d "password=${{ env.CB_PASSWORD }}" \
98
+ -d "username=${{ env.CB_USERNAME }}" \
99
+ -d 'port=SAME'
100
+
101
+ echo "Cluster initialization complete"
102
+
103
+ - name: Create test bucket
104
+ run: |
105
+ echo "Creating test bucket..."
106
+
107
+ # Wait for cluster to be fully initialized
108
+ sleep 5
109
+
110
+ # Create travel-sample bucket (or a test bucket)
111
+ curl -s -X POST http://localhost:8091/pools/default/buckets \
112
+ -u "${{ env.CB_USERNAME }}:${{ env.CB_PASSWORD }}" \
113
+ -d 'name=${{ env.CB_MCP_TEST_BUCKET }}' \
114
+ -d 'bucketType=couchbase' \
115
+ -d 'ramQuota=256' \
116
+ -d 'flushEnabled=1'
117
+
118
+ # Wait for bucket to be ready
119
+ echo "Waiting for bucket to be ready..."
120
+ for i in {1..30}; do
121
+ if curl -s -u "${{ env.CB_USERNAME }}:${{ env.CB_PASSWORD }}" \
122
+ http://localhost:8091/pools/default/buckets/${{ env.CB_MCP_TEST_BUCKET }} | grep -q '"status":"healthy"'; then
123
+ echo "Bucket is healthy"
124
+ break
125
+ fi
126
+ echo "Waiting for bucket... ($i/30)"
127
+ sleep 2
128
+ done
129
+
130
+ - name: Create primary index
131
+ run: |
132
+ echo "Creating primary index..."
133
+ sleep 5
134
+ curl -s -X POST http://localhost:8093/query/service \
135
+ -u "${{ env.CB_USERNAME }}:${{ env.CB_PASSWORD }}" \
136
+ -d "statement=CREATE PRIMARY INDEX ON \`${{ env.CB_MCP_TEST_BUCKET }}\`._default._default" \
137
+ || echo "Primary index may already exist or query service not ready"
138
+
139
+ - name: Insert test documents
140
+ run: |
141
+ echo "Inserting test documents..."
142
+ curl -s -X POST http://localhost:8093/query/service \
143
+ -u "${{ env.CB_USERNAME }}:${{ env.CB_PASSWORD }}" \
144
+ -d "statement=INSERT INTO \`${{ env.CB_MCP_TEST_BUCKET }}\`._default._default (KEY, VALUE) VALUES {\"type\": \"test\", \"name\": \"Test Document 1\", \"id\": 1})" \
145
+ || echo "Insert may have failed"
146
+
147
+ curl -s -X POST http://localhost:8093/query/service \
148
+ -u "${{ env.CB_USERNAME }}:${{ env.CB_PASSWORD }}" \
149
+ -d "statement=INSERT INTO \`${{ env.CB_MCP_TEST_BUCKET }}\`._default._default (KEY, VALUE) VALUES ('test-doc-2', {\"type\": \"test\", \"name\": \"Test Document 2\", \"id\": 2})" \
150
+ || echo "Insert may have failed"
151
+
152
+ # ============================================
153
+ # STDIO Transport Tests
154
+ # ============================================
155
+ - name: Run STDIO integration tests
156
+ if: matrix.transport == 'stdio'
157
+ env:
158
+ CB_CONNECTION_STRING: couchbase://localhost
159
+ CB_MCP_TRANSPORT: stdio
160
+ PYTHONPATH: src
161
+ run: |
162
+ echo "Running tests with STDIO transport..."
163
+ uv run pytest tests/ -v --tb=short
164
+
165
+ # ============================================
166
+ # HTTP Transport Tests
167
+ # ============================================
168
+ - name: Start MCP server (HTTP)
169
+ if: matrix.transport == 'http'
170
+ env:
171
+ CB_CONNECTION_STRING: couchbase://localhost
172
+ CB_MCP_TRANSPORT: http
173
+ CB_MCP_HOST: 127.0.0.1
174
+ CB_MCP_PORT: 8000
175
+ PYTHONPATH: src
176
+ run: |
177
+ echo "Starting MCP server with HTTP transport..."
178
+ uv run python -m mcp_server &
179
+ SERVER_PID=$!
180
+ echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV
181
+
182
+ # Wait for server to be ready (check if port is listening)
183
+ echo "Waiting for HTTP server to be ready..."
184
+ for i in {1..30}; do
185
+ if nc -z 127.0.0.1 8000 2>/dev/null; then
186
+ echo "HTTP server is ready"
187
+ break
188
+ fi
189
+ echo "Waiting for HTTP server... ($i/30)"
190
+ sleep 1
191
+ done
192
+
193
+ - name: Run HTTP transport tests
194
+ if: matrix.transport == 'http'
195
+ env:
196
+ CB_CONNECTION_STRING: couchbase://localhost
197
+ CB_MCP_TRANSPORT: http
198
+ CB_MCP_HOST: 127.0.0.1
199
+ CB_MCP_PORT: 8000
200
+ MCP_SERVER_URL: http://127.0.0.1:8000/mcp
201
+ PYTHONPATH: src
202
+ run: |
203
+ echo "Running tests with HTTP transport..."
204
+ uv run pytest tests/ -v --tb=short
205
+
206
+ - name: Stop HTTP server
207
+ if: matrix.transport == 'http' && always()
208
+ run: |
209
+ if [ -n "$SERVER_PID" ]; then
210
+ kill $SERVER_PID 2>/dev/null || true
211
+ fi
212
+
213
+ # ============================================
214
+ # SSE Transport Tests
215
+ # ============================================
216
+ - name: Start MCP server (SSE)
217
+ if: matrix.transport == 'sse'
218
+ env:
219
+ CB_CONNECTION_STRING: couchbase://localhost
220
+ CB_MCP_TRANSPORT: sse
221
+ CB_MCP_HOST: 127.0.0.1
222
+ CB_MCP_PORT: 8000
223
+ PYTHONPATH: src
224
+ run: |
225
+ echo "Starting MCP server with SSE transport..."
226
+ uv run python -m mcp_server &
227
+ SERVER_PID=$!
228
+ echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV
229
+
230
+ # Wait for server to be ready (check if port is listening)
231
+ echo "Waiting for SSE server to be ready..."
232
+ for i in {1..30}; do
233
+ if nc -z 127.0.0.1 8000 2>/dev/null; then
234
+ echo "SSE server is ready"
235
+ break
236
+ fi
237
+ echo "Waiting for SSE server... ($i/30)"
238
+ sleep 1
239
+ done
240
+
241
+ - name: Run SSE transport tests
242
+ if: matrix.transport == 'sse'
243
+ env:
244
+ CB_CONNECTION_STRING: couchbase://localhost
245
+ CB_MCP_TRANSPORT: sse
246
+ CB_MCP_HOST: 127.0.0.1
247
+ CB_MCP_PORT: 8000
248
+ MCP_SERVER_URL: http://127.0.0.1:8000/sse
249
+ PYTHONPATH: src
250
+ run: |
251
+ echo "Running tests with SSE transport..."
252
+ uv run pytest tests/ -v --tb=short
253
+
254
+ - name: Stop SSE server
255
+ if: matrix.transport == 'sse' && always()
256
+ run: |
257
+ if [ -n "$SERVER_PID" ]; then
258
+ kill $SERVER_PID 2>/dev/null || true
259
+ fi
260
+
261
+ # ============================================
262
+ # Test Summary
263
+ # ============================================
264
+ test-summary:
265
+ name: Test Summary
266
+ permissions: {}
267
+ runs-on: ubuntu-latest
268
+ needs: [integration-tests]
269
+ if: always()
270
+ steps:
271
+ - name: Check test results
272
+ run: |
273
+ echo "=== Test Results Summary ==="
274
+ echo "Integration Tests: ${{ needs.integration-tests.result }}"
275
+ echo ""
276
+
277
+ if [ "${{ needs.integration-tests.result }}" == "failure" ]; then
278
+ echo "❌ Some tests failed"
279
+ exit 1
280
+ elif [ "${{ needs.integration-tests.result }}" == "cancelled" ]; then
281
+ echo "⚠️ Tests were cancelled"
282
+ exit 1
283
+ else
284
+ echo "✅ All tests passed!"
285
+ fi
@@ -141,7 +141,9 @@ jobs:
141
141
 
142
142
  - name: Notify completion
143
143
  if: success()
144
+ env:
145
+ VERSION: ${{ steps.version.outputs.version }}
144
146
  run: |
145
- echo "MCP Registry updated successfully for version ${{ steps.version.outputs.version }}"
146
- echo "Docker image: docker.io/couchbaseecosystem/mcp-server-couchbase:${{ steps.version.outputs.version }}"
147
- echo "PyPI package: couchbase-mcp-server==${{ steps.version.outputs.version }}"
147
+ echo "MCP Registry updated successfully for version $VERSION"
148
+ echo "Docker image: docker.io/couchbaseecosystem/mcp-server-couchbase:$VERSION"
149
+ echo "PyPI package: couchbase-mcp-server==$VERSION"
@@ -19,12 +19,21 @@ Dockerfile: https://github.com/Couchbase-Ecosystem/mcp-server-couchbase/blob/mai
19
19
  - Upsert a document by ID to a specified scope and collection
20
20
  - Delete a document by ID from a specified scope and collection
21
21
  - Run a [SQL++ query](https://www.couchbase.com/sqlplusplus/) on a specified scope
22
+ - Queries are automatically scoped to the specified bucket and scope, so use collection names directly (e.g., use `SELECT * FROM users` instead of `SELECT * FROM bucket.scope.users`)
22
23
  - 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.
23
24
  - Get the status of the MCP server
24
25
  - Check the cluster credentials by connecting to the cluster
25
26
  - List all indexes in the cluster with their definitions, with optional filtering by bucket, scope, collection and index name.
26
27
  - Get index recommendations from Couchbase Index Advisor for a given SQL++ query to optimize query performance
27
28
  - Get cluster health status and list of all running services
29
+ - Query performance analysis tools using:
30
+ - Get longest running queries by average service time
31
+ - Get most frequently executed queries
32
+ - Get queries with the largest response sizes
33
+ - Get queries with the largest result counts
34
+ - Get queries that use a primary index (potential performance concern)
35
+ - Get queries that don't use a covering index
36
+ - Get queries that are not selective (index scans return many more documents than final result)
28
37
 
29
38
  ## Usage
30
39
 
@@ -1,3 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: couchbase-mcp-server
3
+ Version: 0.5.3
4
+ Summary: Couchbase MCP Server - The Developer Data Platform for Critical Applications in Our AI World
5
+ Project-URL: Homepage, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase
6
+ Project-URL: Documentation, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase#readme
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
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Database
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
+ Provides-Extra: dev
21
+ Requires-Dist: pre-commit==4.2.0; extra == 'dev'
22
+ Requires-Dist: pytest-asyncio==0.24.0; extra == 'dev'
23
+ Requires-Dist: pytest==8.3.3; extra == 'dev'
24
+ Requires-Dist: ruff==0.12.5; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
1
27
  # Couchbase MCP Server
2
28
 
3
29
  An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase that allows LLMs to directly interact with Couchbase clusters.
@@ -21,12 +47,21 @@ An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase th
21
47
  - Upsert a document by ID to a specified scope and collection
22
48
  - Delete a document by ID from a specified scope and collection
23
49
  - Run a [SQL++ query](https://www.couchbase.com/sqlplusplus/) on a specified scope
50
+ - Queries are automatically scoped to the specified bucket and scope, so use collection names directly (e.g., use `SELECT * FROM users` instead of `SELECT * FROM bucket.scope.users`)
24
51
  - 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.
25
52
  - Get the status of the MCP server
26
53
  - Check the cluster credentials by connecting to the cluster
27
54
  - List all indexes in the cluster with their definitions, with optional filtering by bucket, scope, collection and index name.
28
55
  - Get index recommendations from Couchbase Index Advisor for a given SQL++ query to optimize query performance
29
56
  - Get cluster health status and list of all running services
57
+ - Query performance analysis tools:
58
+ - Get longest running queries by average service time
59
+ - Get most frequently executed queries
60
+ - Get queries with the largest response sizes
61
+ - Get queries with the largest result counts
62
+ - Get queries that use a primary index (potential performance concern)
63
+ - Get queries that don't use a covering index
64
+ - Get queries that are not selective (index scans return many more documents than final result)
30
65
 
31
66
  ## Prerequisites
32
67
 
@@ -409,6 +444,21 @@ The Couchbase MCP server can also be used as a managed server in your agentic ap
409
444
  - 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.
410
445
  - 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).
411
446
 
447
+ ## Integration testing
448
+
449
+ We provide high-level MCP integration tests to verify that the server exposes the expected tools and that they can be invoked against a demo Couchbase cluster.
450
+
451
+ 1. Export demo cluster credentials:
452
+ - `CB_CONNECTION_STRING`
453
+ - `CB_USERNAME`
454
+ - `CB_PASSWORD`
455
+ - Optional: `CB_MCP_TEST_BUCKET` (a bucket to probe during the tests)
456
+ 2. Run the tests:
457
+
458
+ ```bash
459
+ uv run pytest tests/ -v
460
+ ```
461
+
412
462
  ---
413
463
 
414
464
  ## 👩‍💻 Contributing
@@ -1,27 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: couchbase-mcp-server
3
- Version: 0.5.2rc5
4
- Summary: Couchbase MCP Server - The Developer Data Platform for Critical Applications in Our AI World
5
- Project-URL: Homepage, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase
6
- Project-URL: Documentation, https://github.com/Couchbase-Ecosystem/mcp-server-couchbase#readme
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
11
- Classifier: Development Status :: 4 - Beta
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Topic :: Database
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
- Provides-Extra: dev
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
-
25
1
  # Couchbase MCP Server
26
2
 
27
3
  An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase that allows LLMs to directly interact with Couchbase clusters.
@@ -45,12 +21,21 @@ An [MCP](https://modelcontextprotocol.io/) server implementation of Couchbase th
45
21
  - Upsert a document by ID to a specified scope and collection
46
22
  - Delete a document by ID from a specified scope and collection
47
23
  - Run a [SQL++ query](https://www.couchbase.com/sqlplusplus/) on a specified scope
24
+ - Queries are automatically scoped to the specified bucket and scope, so use collection names directly (e.g., use `SELECT * FROM users` instead of `SELECT * FROM bucket.scope.users`)
48
25
  - 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.
49
26
  - Get the status of the MCP server
50
27
  - Check the cluster credentials by connecting to the cluster
51
28
  - List all indexes in the cluster with their definitions, with optional filtering by bucket, scope, collection and index name.
52
29
  - Get index recommendations from Couchbase Index Advisor for a given SQL++ query to optimize query performance
53
30
  - Get cluster health status and list of all running services
31
+ - Query performance analysis tools:
32
+ - Get longest running queries by average service time
33
+ - Get most frequently executed queries
34
+ - Get queries with the largest response sizes
35
+ - Get queries with the largest result counts
36
+ - Get queries that use a primary index (potential performance concern)
37
+ - Get queries that don't use a covering index
38
+ - Get queries that are not selective (index scans return many more documents than final result)
54
39
 
55
40
  ## Prerequisites
56
41
 
@@ -433,6 +418,21 @@ The Couchbase MCP server can also be used as a managed server in your agentic ap
433
418
  - 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.
434
419
  - 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).
435
420
 
421
+ ## Integration testing
422
+
423
+ We provide high-level MCP integration tests to verify that the server exposes the expected tools and that they can be invoked against a demo Couchbase cluster.
424
+
425
+ 1. Export demo cluster credentials:
426
+ - `CB_CONNECTION_STRING`
427
+ - `CB_USERNAME`
428
+ - `CB_PASSWORD`
429
+ - Optional: `CB_MCP_TEST_BUCKET` (a bucket to probe during the tests)
430
+ 2. Run the tests:
431
+
432
+ ```bash
433
+ uv run pytest tests/ -v
434
+ ```
435
+
436
436
  ---
437
437
 
438
438
  ## 👩‍💻 Contributing
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "couchbase-mcp-server"
3
- version = "0.5.2rc5"
3
+ version = "0.5.3"
4
4
  description = "Couchbase MCP Server - The Developer Data Platform for Critical Applications in Our AI World"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10,<3.14"
@@ -35,6 +35,8 @@ couchbase-mcp-server = "mcp_server:main"
35
35
  dev = [
36
36
  "ruff==0.12.5",
37
37
  "pre-commit==4.2.0",
38
+ "pytest==8.3.3",
39
+ "pytest-asyncio==0.24.0",
38
40
  ]
39
41
 
40
42
  # Ruff configuration
@@ -124,6 +126,11 @@ indent-style = "space"
124
126
  skip-magic-trailing-comma = false
125
127
  line-ending = "auto"
126
128
 
129
+ # Pytest configuration
130
+ [tool.pytest.ini_options]
131
+ asyncio_mode = "strict"
132
+ asyncio_default_fixture_loop_scope = "function"
133
+
127
134
  # Build system configuration
128
135
  [build-system]
129
136
  requires = ["hatchling"]
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/Couchbase-Ecosystem/mcp-server-couchbase",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.5.2rc5",
9
+ "version": "0.5.3",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "pypi",
13
13
  "identifier": "couchbase-mcp-server",
14
- "version": "0.5.2rc5",
14
+ "version": "0.5.3",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -172,7 +172,7 @@
172
172
  },
173
173
  {
174
174
  "registryType": "oci",
175
- "identifier": "docker.io/couchbaseecosystem/mcp-server-couchbase:0.5.2rc5",
175
+ "identifier": "docker.io/couchbaseecosystem/mcp-server-couchbase:0.5.3",
176
176
  "transport": {
177
177
  "type": "stdio"
178
178
  },
@@ -16,6 +16,13 @@ from .kv import (
16
16
 
17
17
  # Query tools
18
18
  from .query import (
19
+ get_longest_running_queries,
20
+ get_most_frequent_queries,
21
+ get_queries_not_selective,
22
+ get_queries_not_using_covering_index,
23
+ get_queries_using_primary_index,
24
+ get_queries_with_large_result_count,
25
+ get_queries_with_largest_response_sizes,
19
26
  get_schema_for_collection,
20
27
  run_sql_plus_plus_query,
21
28
  )
@@ -47,6 +54,13 @@ ALL_TOOLS = [
47
54
  get_index_advisor_recommendations,
48
55
  list_indexes,
49
56
  get_cluster_health_and_services,
57
+ get_queries_not_selective,
58
+ get_queries_not_using_covering_index,
59
+ get_queries_using_primary_index,
60
+ get_queries_with_large_result_count,
61
+ get_queries_with_largest_response_sizes,
62
+ get_longest_running_queries,
63
+ get_most_frequent_queries,
50
64
  ]
51
65
 
52
66
  __all__ = [
@@ -65,6 +79,13 @@ __all__ = [
65
79
  "get_index_advisor_recommendations",
66
80
  "list_indexes",
67
81
  "get_cluster_health_and_services",
82
+ "get_queries_not_selective",
83
+ "get_queries_not_using_covering_index",
84
+ "get_queries_using_primary_index",
85
+ "get_queries_with_large_result_count",
86
+ "get_queries_with_largest_response_sizes",
87
+ "get_longest_running_queries",
88
+ "get_most_frequent_queries",
68
89
  # Convenience
69
90
  "ALL_TOOLS",
70
91
  ]