Skip to content

Add bucket management tools (create/update/delete/flush/compact/load_sample)#195

Open
celticht32 wants to merge 3 commits into
couchbase:mainfrom
celticht32:feat/bucket-management-tools
Open

Add bucket management tools (create/update/delete/flush/compact/load_sample)#195
celticht32 wants to merge 3 commits into
couchbase:mainfrom
celticht32:feat/bucket-management-tools

Conversation

@celticht32

Copy link
Copy Markdown

⚠️ This PR stacks on top of #187. Its diff includes both #187's index-management code and this PR's bucket-management code because #187 is still under review and its branch doesn't exist on upstream. Once #187 merges, GitHub will auto-shrink this diff to just the 4 new bucket-admin files:

  • src/cb_mcp/tools/bucket_admin.py
  • src/cb_mcp/tools/__init__.py (registration additions)
  • src/cb_mcp/utils/bucket_admin_rest.py
  • tests/unit/test_bucket_admin.py

If you'd like to review just the bucket-management changes in isolation before #187 lands, view the diff at: celticht32/mcp-server-couchbase@feat/index-management-tools...feat/bucket-management-tools

Phase 2 of the phased admin-tool contribution discussed in #157. Follows the same shape and safety model as #187.

What this adds

Six tools that complete the bucket lifecycle the server currently only reads (get_buckets_in_cluster shows them; these create, update, and destroy them):

  • create_bucket — POST /pools/default/buckets. Structured fields (name + ram_quota_mb + optional bucket_type / storage_backend / replica_number / eviction_policy / flush_enabled / durability_min_level / etc.) or a raw body dict. Both paths run through the same allow-listed key validator.
  • update_bucket — POST /pools/default/buckets/{name}. Same shape as create; create-only fields (bucket_type, storage_backend, conflict_resolution_type, num_vbuckets) intentionally omitted.
  • delete_bucket — DELETE /pools/default/buckets/{name}. Requires both confirm=True and confirm_name matching the target bucket exactly — matches the Couchbase Web Console "type the bucket name to delete" pattern.
  • flush_bucket — POST .../controller/doFlush. Requires confirm=True. Server enforces flushEnabled=true on the bucket separately.
  • compact_bucket — POST .../controller/compactBucket or .../controller/cancelBucketCompaction per action="start"|"cancel".
  • load_sample_bucket — POST /sampleBuckets/install with a JSON array. Sample name allow-listed against the documented set (travel-sample, beer-sample, gamesim-sample).

REST goes through a new utils/bucket_admin_rest.py helper that reuses _extract_hosts_from_connection_string and _determine_ssl_verification from utils/index_utils.py — same pattern utils/index_settings.py uses in #187, so multi-host fallback, TLS detection, and Capella root-CA handling stay consistent.

Why it's shaped this way

Follows the conventions #187 established:

  • ctx-first tool functions, dict returns, raise on error, registration via tools/__init__.py lists + TOOL_ANNOTATIONS.
  • Reuses ADMIN_WRITE_TOOLS — bucket lifecycle loads only when read_only_mode is false AND admin_write_mode is true. Bucket create/delete is at least as privileged as index DDL.
  • Same _require_write_scope() shape as index_admin.py. When an OAuth token is present the caller must additionally hold the write scope.
  • Structured args AND raw body dict, both validated against the same allow-list of documented REST form keys. A permitted key set cannot be smuggled around: unknown keys are rejected before the request is built.
  • All identifiers going into URL paths (bucket_name, sample-install target) are validated against the documented Couchbase bucket-name charset ([A-Za-z0-9._%-]{1,100}) AND then URL-encoded via _encode_path_segment before interpolation. % is a valid bucket-name character per Couchbase docs, so a name like %2f%2e%2e passes the charset check; encoding it before insertion makes sure the server can't route on the decoded form.
  • compact_bucket's controller path is chosen from a small allow-list ({"start", "cancel"}compactBucket / cancelBucketCompaction) rather than accepting an arbitrary controller name.
  • load_sample_bucket's sample name is validated against the documented sample-bucket allow-list.
  • Booleans render as lowercase "true"/"false" in the form body (Couchbase REST rejects Python's str(True)). Dicts render as JSON (for autoCompactionSettings etc.). Ints render bare.

Testing

Unit tests in tests/unit/test_bucket_admin.py (no cluster required): bucket-name validator (charset, length, non-string, path-traversal characters), extra-key allow-list, form-value rendering (bool/int/dict), write-scope gate (present / missing / no-token), argument construction (snake→camel mapping), confirm-gate coverage (delete requires confirm=True AND matching confirm_name; flush requires confirm=True), REST URL construction (correct method, correct path per endpoint, TLS uses https+18091), URL path encoding (%2f%2e%2e%252f%252e%252e), and allow-list matching between the tool and REST layers.

  • ruff check and ruff format --check pass against pinned ruff 0.12.5.
  • Full unit suite green — 477 tests pass (existing 425 + 52 new).
  • Tested on Python 3.10 syntax (ast.parse with feature_version=(3, 10)).

Open questions for maintainers

Same three from #187 apply here; happy to align with whatever you decide on that PR:

  1. Naming. Verb-first for the write ops (create_bucket, delete_bucket, etc.) to match Add index management tools (create/drop/build + GSI settings) #187's create_index / drop_index. No admin_bucket_settings_* because bucket settings ARE the bucket — update_bucket covers that surface.
  2. Admin-write flag. These load under the same --admin-write-mode / CB_MCP_ADMIN_WRITE_MODE flag Add index management tools (create/drop/build + GSI settings) #187 introduced. If you decide to collapse that into read_only_mode on Add index management tools (create/drop/build + GSI settings) #187, I'll follow suit here.
  3. Error convention. Same raised-exception shape as Add index management tools (create/drop/build + GSI settings) #187. Structured ok()/err() envelope deferred to a future PR (best done uniformly at the registration layer).

Refs #157, #187.

@celticht32 celticht32 changed the title Feat/bucket management toolsAdd bucket management tools (create/update/delete/flush/compact/load_sample) Add bucket management tools (create/update/delete/flush/compact/load_sample) Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant