Fix Nextcloud UUID principals for DAV + robust OCS sharing (paths + internal UUID users)#638
Open
Khazhinov wants to merge 10 commits into
Open
Fix Nextcloud UUID principals for DAV + robust OCS sharing (paths + internal UUID users)#638Khazhinov wants to merge 10 commits into
Khazhinov wants to merge 10 commits into
Conversation
added 3 commits
March 20, 2026 14:48
Use DAV current-user-principal + cal:calendar-home-set and card:addressbook-home-set to avoid empty calendars/contacts when Nextcloud uses UUID principals. No functional interface changes.
Some Nextcloud contacts contain invalid BDAY values that break pythonvCard4 parsing. Catch per-contact parsing errors and retry after removing all BDAY lines so a single bad contact doesn't prevent loading the whole addressbook.
Add server-side CardDAV filtering (card:text-match on vCard FN) with optional RU->LAT transliteration, plus best-effort limit to avoid timeouts when addressbooks contain many contacts. Keep per-contact vCard parsing resilient to invalid BDAY so one bad contact doesn't break the whole addressbook.
The current WebDAV client builds paths from `NEXTCLOUD_USERNAME`. On this Nextcloud instance the files WebDAV home lives under UUID principals, so `PROPFIND`/`SEARCH` hit `/files/<username>/` and return 404. Fix: - Discover `current-user-principal` from `PROPFIND /remote.php/dav/`. - Use the discovered principal id to build WebDAV base paths: `/remote.php/dav/files/<uuid>/`. - Update WebDAV SEARCH scope and tag/report prefix stripping to use the same UUID principal. Notes: - Also fixes a small syntax error in the contacts tool signature that could prevent the MCP server from starting after rebuilds. Made-with: Cursor
added 6 commits
March 20, 2026 17:37
Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
Owner
|
Hi @Khazhinov thanks for your contribution! I've recently replaced my fork of the Thanks 🙏 |
|
vkhazhinov seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
Vitexus
pushed a commit
to Vitexus/nextcloud-mcp-server
that referenced
this pull request
Jul 11, 2026
The Tenant Fleet dashboard panel "Chunk density distribution (chunks/MB)"
renders increase(astrolabe_document_chunk_density_chunks_per_mb_bucket[...]),
an ingest-time flow histogram observed once per document at parse. It does not
represent the density distribution of the documents currently resident in
Qdrant (monotonic, reset-on-restart, window-scoped).
Add a current-state snapshot metric recomputed periodically from live Qdrant
contents:
- Persist source_bytes (ingested_byte_size) in the Qdrant point payload
(payload_keys.SOURCE_BYTES) — the density denominator, previously computed at
ingest and then discarded. Numerator (total_chunks) is already on every point.
- New GaugeHistogram astrolabe_qdrant_chunk_density_chunks_per_mb_current
(custom collector, doc_type label, buckets shared with the ingest histogram
via CHUNK_DENSITY_BUCKETS) — the correct Prometheus type for a snapshot
distribution that rises and falls.
- vector_density_snapshot_task scrolls chunk_index=0 non-placeholder points on
its own slower cadence, computes per-doc_type density, and publishes the
snapshot. Scan cap surfaced via astrolabe_qdrant_chunk_density_snapshot_truncated
(no silent cap).
- Forward-only coverage: only documents (re)ingested after this ships carry
source_bytes. Docs without a usable size are reported via
astrolabe_qdrant_chunk_density_uncovered_documents{doc_type} so partial
coverage is explicit rather than silently shrinking the histogram.
- Config knobs VECTOR_DENSITY_SNAPSHOT_{ENABLED,INTERVAL,MAX_DOCUMENTS}; task
spawned in both app lifespan branches, gated on the enable flag.
Tests: unit (bucketing, cumulative/gcount/gsum exposition, snapshot replace,
uncovered/truncated gauges, compute pagination/truncation/failure-swallow) and
integration (compute over a real in-memory Qdrant engine: covered vs uncovered
vs excluded-placeholder, truncation signalling).
Deck cbcoutinho#638 (board 9). Cross-repo payload contract with the astrolabe-cloud-website
external processor to be mirrored as a follow-up (board 11).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Nextcloud frequently uses a UUID-based DAV principal for current-user-principal. The MCP server client previously built CalDAV/CardDAV “home” paths from NEXTCLOUD_USERNAME, which could lead to empty calendars/events and broken addressbook
resolution.
This MR includes:
Correct principal discovery for CalDAV/CardDAV (UUID principals)
• current-user-principal → discover cal:calendar-home-set / card:addressbook-home-set
• cache discovered home-set URLs and fall back to username-based paths only if discovery fails
Fix & performance hardening for CardDAV contacts
• nc_contacts_list_contacts now supports:
• query (server-side CardDAV filtering via card:text-match on vCard FN)
• limit (best-effort server-side limit to avoid huge responses/timeouts)
• query is best-effort extended with RU→LAT transliteration (e.g. search “Агарков” matches vCards storing “Agarkov”)
• vCard parsing is resilient to invalid BDAY: a single broken contact no longer prevents loading the whole addressbook
Fix WebDAV file browsing/search on UUID-principal Nextcloud
• WebDAV “files home” base path now uses the discovered UUID principal (not NEXTCLOUD_USERNAME), so:
• nc_webdav_list_directory no longer fails with 404
• nc_webdav_find_by_name no longer fails with 404
Fix OCS sharing/public link generation on this Nextcloud
• Normalize inputs for /ocs/v2.php/apps/files_sharing/api/v1/shares:
• decode WebDAV href/%xx segments into decoded file/folder path before calling OCS
• support href-like paths by stripping /remote.php/dav/files//... prefix
• For share_type=0 (internal user share):
• resolve shareWith to internal UUID user id via /ocs/v2.php/cloud/users?search=...
• if “sharing with yourself” is forbidden (403), automatically fall back to share_type=3 (public link) for the same path
Files / Components
• nextcloud_mcp_server/client/calendar.py
• nextcloud_mcp_server/client/contacts.py
• nextcloud_mcp_server/server/contacts.py
• nextcloud_mcp_server/client/webdav.py
• nextcloud_mcp_server/client/sharing.py
Changes in MCP tools
• nc_contacts_list_contacts(addressbook, query?, limit?)
• query optional, server-side filtering by vCard FN
• limit optional (defaults to 50)
• Sharing behavior (tool signature unchanged) now works reliably for:
• internal user shares (share_type=0) with correct UUID shareWith
• public links (share_type=3) even when paths originate from WebDAV (encoded/href-like)
Test plan
• call nc_calendar_list_calendars → result is non-empty.
3. Verify addressbooks load:
• call nc_contacts_list_addressbooks → includes the relevant addressbook (e.g. “Учётные записи”).
4. Verify contacts search:
• call nc_contacts_list_contacts with query="Агарков" and small limit (e.g. 5).
5. Verify contacts “no query” is capped:
• call nc_contacts_list_contacts with only addressbook → returns up to default limit (50).
6. Verify WebDAV file browsing/search:
• call nc_webdav_list_directory(path="") → no 404; returns entries.
• call nc_webdav_find_by_name(pattern="%%") → returns matching files.
7. Verify sharing / public links:
• get a file path via nc_webdav_list_directory
• call nc_share_create with:
• share_type=0, share_with=, read permissions for a docx path
• expected: no HTTP 404; returns usable url (internally falls back to share_type=3 when needed)
Notes
• Backwards compatibility: existing callers that pass only addressbook still work; the server caps results by default to prevent timeouts on large addressbooks.
• Explicit types:
• share_type=0 internal user share
• share_type=3 public link