fix: address PR review feedback for Collectives support

- Validate OCS envelope status before unwrapping data (raise OCSError on
  statuscode >= 400)
- Fix test data: filePath should be "" for root-level pages, not filename
- Catch specific exceptions (HTTPStatusError, OSError) instead of bare
  Exception in WebDAV content fetch, include error in log message
- Return updated resource data from update_collective, move_page, and
  set_page_emoji instead of discarding API responses
- Fix create_page docstring to mention collectivePath/filePath/fileName
- Remove unused additional_headers parameter from _get_ocs_headers
- Add unit test for OCS error status validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-03-25 08:07:37 +01:00
co-authored by Claude Opus 4.6
parent 32f5a0fe52
commit e5ad625a66
3 changed files with 66 additions and 25 deletions
+22 -9
View File
@@ -1,33 +1,46 @@
"""Client for Nextcloud Collectives app API (OCS)."""
import logging
from typing import Any
from nextcloud_mcp_server.client.base import BaseNextcloudClient
logger = logging.getLogger(__name__)
API_BASE = "/ocs/v2.php/apps/collectives/api/v1.0"
class OCSError(Exception):
"""Error returned in the OCS response envelope."""
def __init__(self, status_code: int, message: str):
self.status_code = status_code
self.message = message
super().__init__(f"OCS error {status_code}: {message}")
class CollectivesClient(BaseNextcloudClient):
"""Client for Nextcloud Collectives app operations."""
app_name = "collectives"
def _get_ocs_headers(
self, additional_headers: dict[str, str] | None = None
) -> dict[str, str]:
def _get_ocs_headers(self) -> dict[str, str]:
"""Get standard headers required for OCS API calls."""
headers = {
return {
"OCS-APIRequest": "true",
"Content-Type": "application/json",
"Accept": "application/json",
}
if additional_headers:
headers.update(additional_headers)
return headers
def _unwrap_ocs(self, response_json: dict[str, Any]) -> Any:
"""Unwrap OCS envelope, returning the data payload."""
return response_json["ocs"]["data"]
"""Unwrap OCS envelope, validating the status before returning data."""
ocs = response_json["ocs"]
meta = ocs.get("meta", {})
status_code = meta.get("statuscode", 200)
if status_code >= 400:
message = meta.get("message", "OCS error")
raise OCSError(status_code, message)
return ocs["data"]
# Collectives