From 9cb0b33ec12afa94e0d92224b47f25916beea990 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Sun, 10 May 2026 20:15:05 +0200 Subject: [PATCH] fix(health): forward api-key to Qdrant /readyz so Cloud probes work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The readiness handler called the configured `qdrant_url/readyz` with a bare httpx.AsyncClient — no headers. That works against a self-hosted Qdrant (where /readyz is anonymous), but Qdrant Cloud's auth gateway returns 403 for any unauthenticated request, including /readyz, /livez and /healthz. Result: every probe against a Cloud cluster fell into the "status 403" branch, the handler returned 503, and the Pod never went Ready — even when the configured `AsyncQdrantClient` itself was authenticating fine for actual collection traffic. Forward `settings.qdrant_api_key` as the `api-key` header (mirroring what `vector/qdrant_client.py:540` already does for the real client). When the key is unset (self-hosted, anonymous case) we send no header, so existing self-hosted deployments are unchanged. Verified end-to-end against Qdrant Cloud: - Without header: GET /readyz -> 403 {"error":"forbidden"} - With api-key: same request shape returns 200 (matches what AsyncQdrantClient.wait() relies on internally). Co-Authored-By: Claude Opus 4.7 (1M context) --- nextcloud_mcp_server/app.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nextcloud_mcp_server/app.py b/nextcloud_mcp_server/app.py index d2c1d1ab..2fa6eff9 100644 --- a/nextcloud_mcp_server/app.py +++ b/nextcloud_mcp_server/app.py @@ -1960,9 +1960,21 @@ def get_app(transport: str = "streamable-http", enabled_apps: list[str] | None = if vector_sync_enabled and qdrant_url: start_time = time.time() + # Self-hosted Qdrant exposes /readyz unauthenticated, but + # Qdrant Cloud's auth gateway returns 403 for any + # unauthenticated request — so we have to forward the same + # api-key the configured AsyncQdrantClient uses (see + # vector/qdrant_client.py). Without this header, every + # readiness probe against a Cloud cluster returns 503, + # blocking the Pod from reaching Ready. + qdrant_headers = ( + {"api-key": settings.qdrant_api_key} if settings.qdrant_api_key else {} + ) try: async with httpx.AsyncClient(timeout=2.0) as client: - response = await client.get(f"{qdrant_url}/readyz") + response = await client.get( + f"{qdrant_url}/readyz", headers=qdrant_headers + ) duration = time.time() - start_time if response.status_code == 200: checks["qdrant"] = "ok"