Starlette 1.0.0 removed the @app.middleware() decorator, which breaks
nextcloud-mcp-server on fresh installs. Pin starlette<1.0 until we
address the full set of breaking changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add collectives_trash_collective and collectives_delete_collective MCP
tools with proper destructiveHint annotations. Refactor integration test
fixture to use MCP tools for cleanup instead of direct httpx/OCS calls.
Optimize _get_ocs_headers() to class-level constant.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The fork (cbcoutinho/qdrant-client fix/fusion-score-threshold) has been
merged upstream as PR #1138 and released in v1.17.0. Remove the git source
override in [tool.uv.sources] to unblock clean PyPI publishing, since git
dependencies are excluded from wheels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When Nextcloud stores CalDAV objects, the server-side filename may differ
from the VTODO/VEVENT UID. The caldav fork constructed object URLs from
the UID instead of the actual <d:href> from REPORT responses, causing
list_todos to return wrong hrefs, delete_todo to silently no-op, and
update_todo to fail.
Upstream caldav v3.0.1 fixes this in _async_request_report_build_resultlist
by passing url=self.url.join(url) when constructing result objects.
Key changes:
- Replace caldav fork with upstream caldav>=3.0.1,<4.0
- Update imports to caldav.aio module
- Add _maybe_await() helper for v3's dual-mode methods that return
either objects or coroutines depending on async context
- Add _async_object_by_uid() to work around upstream's get_object_by_uid
not being async-aware (it iterates a coroutine synchronously)
- Adapt save_event/save_todo (no longer return tuples)
- Pass url=calendar.url.join(href) in _search_events_by_date
- Pass include_completed=True in list_todos to match previous behavior
- Add integration test for filename != UID scenario
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>