Commit Graph

1362 Commits

Author SHA1 Message Date
Chris Coutinho dfc81923ba fix: resolve CI linting issues for Astroglobe
Fix all ESLint, Stylelint, PHP CS Fixer, and Psalm workflow errors.

Changes:
- ESLint fixes:
  - Remove unused APP_NAME constant
  - Remove unused TextBoxOutline and TextBoxRemoveOutline components
  - Remove unused container variable in adminSettings.js
  - Auto-fix trailing commas, line breaks, attribute ordering
- PHP CS Fixer:
  - Add trailing commas after last function parameters
  - Convert double quotes to single quotes in log messages
  - Remove unused NoCSRFRequired import
  - Fix arrow function formatting
- Stylelint:
  - Update config to use @nextcloud/stylelint-config
  - Fix extends directive (was using non-existent package)
- Psalm workflow:
  - Fix jq object indexing (.include[0] instead of .[0])
  - Correctly extract OCP version from matrix output

All checks now pass locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:54 +01:00
Chris Coutinho 5a6205476a ci: add consolidated GitHub workflow for Astroglobe app
Create single workflow that includes all key checks from Nextcloud app
skeleton instead of copying 14 separate workflow files.

Changes:
- Create astroglobe-ci.yml workflow:
  - Triggers on PRs modifying third_party/astroglobe/
  - Detects frontend vs PHP changes separately
  - Frontend checks: Node.js build, ESLint, Stylelint
  - PHP checks: CS Fixer, Psalm static analysis
  - Uses official Nextcloud actions (version-matrix, read-package-engines)
  - Runs checks only for changed file types
  - Summary job for branch protection rules

Benefits:
- Consolidated workflow easier to maintain than 14 files
- Follows Nextcloud app quality standards
- Catches issues before deployment
- Automatic checks on every PR

Based on Nextcloud app skeleton workflows from:
https://github.com/nextcloud/.github

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:53 +01:00
Chris Coutinho be7f512244 docs: document deployment modes and Nextcloud log querying
Update ADR-018 with comprehensive deployment architecture and add
Nextcloud application log querying patterns to CLAUDE.md.

Changes:
- ADR-018 deployment modes documentation:
  - Mode 1: Basic single-user (development/simple)
  - Mode 2: Basic multi-user pass-through (no OIDC)
  - Mode 3: OAuth multi-user with progressive consent
  - Authentication flows for each mode
  - Communication path diagrams
  - Implementation examples
  - Use cases and limitations
- CLAUDE.md additions:
  - Nextcloud application log querying patterns
  - Common jq filters for debugging
  - Log structure documentation
  - App-specific filtering examples

Benefits:
- Clear guidance on deployment architecture selection
- Documented authentication flows for all scenarios
- Easier debugging with log query patterns
- Complete reference for mode-specific configurations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:53 +01:00
Chris Coutinho 5eec34c17e feat(auth): implement refresh token rotation for Nextcloud OIDC
Add support for one-time use refresh tokens with automatic rotation
to align with Nextcloud OIDC security model.

Changes:
- TokenBrokerService improvements:
  - Add user_id parameter to refresh methods
  - Detect and store rotated refresh tokens
  - Add offline_access scope to token requests
  - Handle refresh token rotation on every use
- Add management API endpoints:
  - /api/v1/webhooks (GET/POST) - List/create webhooks
  - /api/v1/webhooks/{id} (DELETE) - Delete webhook
  - /api/v1/search (POST) - Unified search
  - /api/v1/chunk-context (GET) - Get chunk context
  - /api/v1/apps (GET) - List installed apps
- Update tests for refresh token rotation
- Add --headed flag to pytest for Playwright debugging

Benefits:
- Aligns with Nextcloud OIDC one-time refresh token model
- Prevents refresh token invalidation after first use
- Enables long-lived background operations
- Provides full webhook lifecycle management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:53 +01:00
Chris Coutinho 656214b162 chore(docker): update app hooks for confidential OAuth client
Configure Astroglobe as a confidential OAuth client with client_secret
to support token refresh for long-lived sessions.

Changes:
- Update install-astroglobe-app hook to:
  - Create confidential client instead of public
  - Add offline_access scope for refresh tokens
  - Extract and store client_secret in system config
  - Display secret (truncated) for verification
- Update trusted-domains hook (formatting)

Benefits:
- Enables automatic token refresh without re-authentication
- Supports long-lived backend operations
- Better security for server-side OAuth flows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:53 +01:00
Chris Coutinho 45fc25d02b feat(astrolabe): enhance unified search and add webhook management
Improve unified search results with chunk/page metadata and add
webhook management capabilities to McpServerClient.

Changes:
- SemanticSearchProvider improvements:
  - Display chunk position (e.g., "Chunk 2/5")
  - Display page numbers for PDFs (e.g., "Page 3/10")
  - Fix file links to open in Files app correctly
  - Fix deck card links to use proper URL format
  - Show metadata in subline before excerpt
  - Use proper icons and thumbnails for each doc type
- McpServerClient webhook methods:
  - listWebhooks() - Get all registered webhooks
  - createWebhook() - Register new webhook
  - deleteWebhook() - Remove webhook registration
  - enableWebhook() / disableWebhook() - Toggle webhook status
  - getWebhookLogs() - Retrieve delivery logs

Benefits:
- Better search result context with chunk and page info
- Clickable links that open correct resources
- Full webhook lifecycle management via API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:47 +01:00
Chris Coutinho 9aec5582db feat(astrolabe): add webhook management UI to admin settings
Add admin interface for configuring real-time webhook sync with
pre-configured presets for common scenarios.

Changes:
- Add webhook presets section to admin settings page
  - Shows available presets filtered by installed apps
  - Enable/disable presets with one click
  - Displays current webhook status
- Add client secret configuration status display
  - Shows whether confidential client is configured
  - Provides setup instructions for optional client secret
- Add adminSettings.js for webhook management
  - Load webhook presets via API
  - Enable/disable webhook presets
  - Handle search settings form submission
- Update vite.config.js to build adminSettings entry point
- Pass clientSecretConfigured flag to template

UI Features:
- Real-time preset status (enabled/disabled)
- One-click enable/disable for webhook bundles
- App-aware filtering (only shows presets for installed apps)
- Clear instructions for requirements and setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:42 +01:00
Chris Coutinho 0f7e87a91c feat(astrolabe): add OAuth token refresh and webhook presets
Implement automatic token refresh and pre-configured webhook bundles
to simplify vector sync configuration.

Changes:
- Add IdpTokenRefresher service for automatic OAuth token renewal
  - Works with both Nextcloud OIDC and external IdPs (Keycloak)
  - Uses OIDC discovery for automatic endpoint detection
  - Supports confidential clients with client_secret
- Add WebhookPresets service with pre-configured bundles:
  - Notes sync (file created/written/deleted in Notes folder)
  - Calendar sync (calendar object created/updated/deleted)
  - Tables sync (row added/updated/deleted, Nextcloud 30+)
  - Forms sync (form submitted, Nextcloud 30+)
- Update ApiController to use automatic token refresh
  - Pass refresh callback to McpTokenStorage
  - Add getWebhookPresets endpoint (admin-only)
  - Add configureWebhooks endpoint for bulk setup
- Update OAuthController for webhook management
- Add new API routes for webhook configuration

Benefits:
- Eliminates manual token refresh
- Simplifies webhook setup with one-click presets
- Provides app-aware filtering (only shows presets for installed apps)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:35 +01:00
Chris Coutinho 5acac804a1 refactor(astrolabe): extract PDF viewer to dedicated component
Replace fragile 20-iteration retry loop with proper Vue lifecycle management.

Changes:
- Create PDFViewer.vue component (~200 lines) with:
  - Proper mounted/beforeUnmount lifecycle hooks
  - Loading/error/content states
  - Page navigation controls
  - PDF document cleanup
  - User-friendly error messages
- Simplify App.vue by removing ~120 lines:
  - Remove loadPdf() and renderPdfPage() methods
  - Remove manual DOM polling with $nextTick() loops
  - Replace PDF template with <PDFViewer> component
- Add pdfjs-dist@4.0.379 dependency

Result: Canvas found on first attempt instead of requiring 20 retries.

Follows patterns from Nextcloud's production files_pdfviewer app and
2025 Vue.js + PDF.js best practices.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:30 +01:00
Chris Coutinho 85db90a2df feat(search): add file_path metadata and chunk offsets to search results
Changes:
- Add file_path to metadata in semantic and BM25 hybrid search algorithms
  for PDF viewer integration (search/semantic.py:161-163, search/bm25_hybrid.py:230-232)
- Include chunk_start_offset, chunk_end_offset, page_number, and page_count
  in search results for rich chunk display (api/management.py:981-1004)
- Add point_id field to SearchResult for batch retrieval (models/semantic.py)
- Fix type narrowing for chunk context API parameters (api/management.py:1102-1111)
- Fix None-safety in doc_types discovery (search/algorithms.py:114)

This enables the Astroglobe UI to display PDF pages at the correct
location for matched chunks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:29 +01:00
Chris Coutinho a026f2eddb chore: update .gitignore for build artifacts and screenshots
Add patterns to ignore:
- Screenshots and test images (*.png, *.jpg, *.jpeg)
- Astroglobe frontend build artifacts (dist/, node_modules/)
- Unrelated third-party apps (third_party/spreed/)
2025-12-18 00:01:29 +01:00
Chris Coutinho 73783b85d5 feat(astrolabe): use proper icons and thumbnails in unified search
Improve search result display to match Nextcloud's native search providers by using mimetype-specific icons and preview thumbnails.

**File Results:**
- Use preview thumbnails for images/PDFs (core.Preview API)
- Use mimetype-specific icon classes (icon-pdf, icon-text, icon-image, etc.)
- Detect folders and use icon-folder appropriately

**Other Document Types:**
- Notes: icon-notes
- Deck Cards: icon-deck
- Calendar: icon-calendar
- News: icon-rss
- Contacts: icon-contacts

**API Changes:**
- Management API now includes mime_type in search results
- SemanticSearchProvider uses IMimeTypeDetector and IPreview services

This makes Astroglobe search results visually consistent with Files, Notes, and other native providers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:24 +01:00
Chris Coutinho 4cce4f6392 feat(astrolabe): add admin search settings and enhanced UI
Add comprehensive admin controls for the unified search provider and enhance the frontend UI with filtering and visualization improvements.

**Admin Settings:**
- Configure default search algorithm (hybrid, semantic, bm25)
- Set fusion method for hybrid search (rrf, dbsf)
- Adjust minimum score threshold (0-100%)
- Set result limit (1-100 results)

**Frontend Enhancements:**
- Add score-based result filtering with slider control
- Add expandable excerpts for search results
- Improve result visualization and formatting
- Add algorithm badge to show search method used

**API Changes:**
- Add `/api/admin/search-settings` POST endpoint
- Add `searchForUnifiedSearch()` method to McpServerClient
- Load and apply admin settings in SemanticSearchProvider

**Technical Details:**
- Settings stored in app config table
- Defaults: hybrid algorithm, rrf fusion, 0% threshold, 20 results
- SemanticSearchProvider respects admin-configured limits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:19 +01:00
Chris Coutinho 24e63a967a ci: Update oidc app 2025-12-18 00:01:18 +01:00
Chris Coutinho dbb6ba333a feat(astrolabe): add unified search provider with clickable file links
Integrate semantic search into Nextcloud's unified search UI. File results now use fileId parameter to properly open files instead of just navigating to the Files app.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 00:01:14 +01:00
Chris Coutinho 97b48ca3dd feat(astrolabe): add 3D PCA visualization for semantic search
- Add Plotly.js 3D scatter plot showing search results in PCA space
- Create shared visualization.py module to avoid code duplication
- Pass include_pca parameter through API chain to enable coordinates
- Fix OAuth redirects to use /settings/user/astroglobe

The visualization shows document embeddings projected to 3D via PCA,
with the query point highlighted in red. Uses Viridis colorscale
for score visualization, matching the existing vector-viz page.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:01:09 +01:00
Chris Coutinho a4106ee20d refactor(astrolabe): reframe UI as semantic search service
Update all user-facing text to focus on Astroglobe as a semantic
search service for Nextcloud users:

- info.xml: New description focusing on finding content by meaning
- Settings sections: Renamed from "MCP Server" to "Astroglobe"
- Personal settings: Reframed as content indexing controls
- Admin settings: Reframed as semantic search administration
- OAuth flow: Explains semantic search benefits to users

Key messaging changes:
- "MCP Server" → "Astroglobe"
- "Grant Background Access" → "Enable Semantic Search"
- "Vector Sync" → "Content Indexing"
- Focus on user benefits: natural language search, finding by meaning

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:01:00 +01:00
Chris Coutinho 21817543ad feat(astrolabe): add Nextcloud PHP app for MCP server management
Adds a native Nextcloud app "Astroglobe" that provides:
- Personal settings: OAuth authorization for background MCP access
- Admin settings: Server status and vector sync monitoring
- API endpoints for MCP server communication

The app uses PKCE OAuth flow to obtain tokens for the MCP server,
enabling features like background vector sync per ADR-018.

Includes:
- PHP app structure (controllers, services, settings)
- Vue.js frontend components
- Docker compose mount configuration
- Installation hook for development testing
- ADR-018 documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:00:40 +01:00
Chris Coutinho a58a14111b feat(vector-sync): enable background sync in OAuth mode
Add multi-user background vector synchronization when running in OAuth
mode with ENABLE_OFFLINE_ACCESS=true. Key changes:

Architecture (oauth_sync.py):
- User Manager task polls RefreshTokenStorage for provisioned users
- Per-user scanner tasks fetch documents using OAuth tokens
- Shared processor pool indexes documents from all users

Token Broker improvements:
- Accept client_id/client_secret instead of encryption_key
- Remove redundant token audience pre-validation (Nextcloud validates)
- Add _rewrite_token_endpoint for Docker internal URL routing
- Remove double-decryption (storage handles encryption internally)

Browser OAuth flow fixes:
- Add 'resource' parameter to request Nextcloud-scoped tokens
- Store and retrieve next_url for proper redirect after consent
- Rewrite token endpoint URLs for internal Docker access

Configuration:
- Add vector_sync_user_poll_interval setting (default: 60s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 20:00:41 +01:00
github-actions[bot] 1a079a41e7 bump: version 0.52.0 → 0.52.1 nextcloud-mcp-server-0.52.1 v0.52.1 2025-12-13 23:24:55 +00:00
Chris Coutinho ebbd3bcc61 Merge pull request #396 from cbcoutinho/feat/deck-vector-search
perf(deck): Optimize card lookup with O(1) metadata-based retrieval
2025-12-14 00:24:25 +01:00
Chris Coutinho 54fdc8addc Merge remote-tracking branch 'origin/master' into feat/deck-vector-search 2025-12-14 00:23:16 +01:00
Chris Coutinho e0320e761c perf(deck): optimize card lookup by storing board_id/stack_id in metadata
Addresses reviewer feedback on PR #395 about O(n²) performance issue.

Changes:
- scanner.py: Add metadata field to DocumentTask with board_id/stack_id
- scanner.py: Populate metadata during deck card scanning (both initial and incremental sync)
- processor.py: Use metadata for O(1) card lookup via get_card() API when available
- processor.py: Fallback to iteration for legacy data without metadata
- context.py: Add _get_deck_metadata_from_qdrant() helper to retrieve metadata from Qdrant
- context.py: Use metadata for fast path lookup in chunk context expansion
- context.py: Add user_id parameter to _fetch_document_text() for metadata retrieval

Performance Impact:
- Before: O(boards × stacks × cards) iteration for each card lookup
- After: O(1) direct API call using stored board_id/stack_id
- Graceful degradation: Falls back to iteration for legacy data

Testing:
- All existing integration tests pass (test_deck_vector_search.py)
- Type checking passes with no new errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-14 00:23:12 +01:00
github-actions[bot] 2b7c308188 bump: version 0.51.0 → 0.52.0 nextcloud-mcp-server-0.52.0 v0.52.0 2025-12-13 22:56:03 +00:00
Chris Coutinho 40ac52654f Merge pull request #395 from cbcoutinho/feat/deck-vector-search
feat(vector): Add Deck card vector search with visualization support
2025-12-13 23:55:31 +01:00
Chris Coutinho 034e405824 build: Add qdrant-client until upstream issue is merged 2025-12-13 23:51:43 +01:00
Chris Coutinho 20404cf3f2 feat(vector): add Deck card vector search with visualization support
Adds comprehensive vector search support for Nextcloud Deck cards,
including semantic search indexing, chunk preview in the vector viz UI,
and proper deep linking to cards.

**Vector Search Indexing**
- Add deck_card scanning in scanner.py (scan_deck_cards function)
- Index cards from non-archived, non-deleted boards
- Store metadata: board_id, board_title, stack_id, stack_title, card_type, duedate, owner
- Content structure: title + "\n\n" + description (matches indexing format)
- Incremental sync based on lastModified timestamp
- Deletion tracking with grace period

**Vector Visualization Support**
- Add deck_card handler in context.py for chunk preview expansion
- Include board_id in search result metadata (bm25_hybrid.py, semantic.py)
- Expose metadata in viz_routes.py JSON responses
- Update vector-viz.js to construct proper Deck URLs: /apps/deck/board/{board_id}/card/{card_id}
- Update vector_viz.html filter label from "Deck" to "Deck Cards"

**Bug Fixes**
- Skip soft-deleted boards (deletedAt > 0) to prevent 403 Forbidden errors
- Applies to scanner, processor, and context expansion code paths
- Deck API returns deleted boards but rejects stack access with 403

**Testing**
- Add integration tests in test_deck_vector_search.py:
  - test_deck_card_semantic_search: Filtered search with doc_type="deck_card"
  - test_deck_card_appears_in_cross_app_search: Cross-app search includes deck cards
  - test_deck_card_chunk_context: Chunk context fetching for viz preview

**Documentation**
- Update README.md: Add Deck cards to semantic search feature list
- Update semantic-search-architecture.md: Document deck_card support
- Update nc_semantic_search tool documentation

**Type Safety**
- Fix type narrowing for page_boundaries (could be None) using cast()
- Fix scanner.py payload None check for type safety

Resolves vector search for Deck cards across indexing, search, and visualization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-13 23:51:18 +01:00
github-actions[bot] 264bb5475c bump: version 0.50.2 → 0.51.0 nextcloud-mcp-server-0.51.0 v0.51.0 2025-12-13 21:24:19 +00:00
Chris Coutinho 6e3f9f6e79 Merge pull request #394 from cbcoutinho/news-link
feat(vector-viz): add news_item support for links and chunk expansion
2025-12-13 22:23:48 +01:00
Chris Coutinho 9d0a993c2a feat(vector-viz): add news_item support for links and chunk expansion
Add support for news_item document type in the vector visualization page:

- Add "News" checkbox to document type filter options
- Add URL handler to link news items to /apps/news/item/{id}
- Add content fetching for news items in chunk context expansion

This enables users to search and view news articles in the vector
visualization, with clickable links back to Nextcloud News and the
ability to expand chunks to see full article context.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:34:47 +01:00
github-actions[bot] cd3e60ba4f bump: version 0.50.1 → 0.50.2 nextcloud-mcp-server-0.50.2 v0.50.2 2025-12-13 14:53:42 +00:00
Chris Coutinho 360299f5f6 Merge pull request #393 from cbcoutinho/fix/news-api-get-item-405-error
fix(news): revert get_item() to use get_items() + filter
2025-12-13 15:53:11 +01:00
Chris Coutinho d61e33113c fix(news): revert get_item() to use get_items() + filter
Reverts the "perf(news): use direct API endpoint for get_item()" change
from commit 92c4bf3 which incorrectly assumed GET /items/{itemId} exists.

The News API (v1-2, v1-3, v2) does not provide a direct endpoint to
retrieve individual items. The only /items/{itemId} routes are POST
operations for marking items read/unread/starred.

Changes:
- Restore original get_item() implementation that fetches all items
  and filters in Python
- Update exception from HTTPStatusError to ValueError
- Restore documentation explaining API limitation
- Update unit tests to mock get_items() instead of _make_request()
- Add test for ValueError when item not found

Fixes vector processor 405 errors when indexing news items.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-13 15:47:27 +01:00
Chris Coutinho 5faf7cf45f Merge pull request #391 from cbcoutinho/renovate/docker.io-library-python-3.12-slim-trixie
chore(deps): update docker.io/library/python:3.12-slim-trixie docker digest to fa48eef
2025-12-13 12:56:55 +01:00
renovate-bot-cbcoutinho[bot] cd922fa750 chore(deps): update docker.io/library/python:3.12-slim-trixie docker digest to fa48eef 2025-12-13 11:07:41 +00:00
github-actions[bot] a4d4c386f7 bump: version 0.50.0 → 0.50.1 nextcloud-mcp-server-0.50.1 v0.50.1 2025-12-12 17:00:34 +00:00
Chris Coutinho c8da826ef7 Merge pull request #382 from cbcoutinho/renovate/mcp-1.x
fix(deps): update dependency mcp to >=1.23,<1.24
2025-12-12 18:00:04 +01:00
Chris Coutinho 5166c2c4d7 test: Add verification test for DNS rebinding protection fix
This test verifies that the MCP 1.23.x DNS rebinding protection fix works
correctly by sending requests with various Host headers that would be
rejected if the protection were enabled.

Test cases:
- Kubernetes service DNS (nextcloud-mcp-server.default.svc.cluster.local:8000)
- Custom domain (mcp.example.com:8000)
- Proxied hostname (proxy.internal:8000)
- Default localhost (localhost:8000)
- Malicious hostname (evil.attacker.com:8000)

Without the fix (enable_dns_rebinding_protection=False), these would fail with:
- 421 Misdirected Request (Host header not in allowed list)
- 403 Forbidden (Origin header not in allowed list)

With the fix, all requests succeed with 200 OK (SSE format).

Test results: All 2 tests passed
- test_accepts_various_host_headers: PASSED
- test_dns_rebinding_protection_is_disabled: PASSED
2025-12-12 17:56:16 +01:00
Chris Coutinho ec70e70a5d fix: Disable DNS rebinding protection for containerized deployments
MCP Python SDK 1.23.0 introduced automatic DNS rebinding protection that
auto-enables when host="127.0.0.1" (the default). This breaks containerized
deployments (Kubernetes, Docker) because the protection rejects requests
with Host headers like "nextcloud-mcp-server.default.svc.cluster.local:8000".

Root cause:
- FastMCP defaults to host="127.0.0.1"
- SDK auto-enables DNS rebinding protection with allowed_hosts=["127.0.0.1:*", "localhost:*", "[::1]:*"]
- K8s/Docker requests use service DNS names or proxied hostnames
- Protection middleware rejects these requests (421 Misdirected Request)

Solution:
- Explicitly pass transport_security=TransportSecuritySettings(enable_dns_rebinding_protection=False)
- Applied to all three FastMCP initializations (OAuth, Smithery, BasicAuth)
- DNS rebinding attacks mitigated by OAuth authentication and network isolation

This fixes issue #373 and enables MCP 1.23.x upgrade in PR #382.

For detailed analysis, see docs/MCP-1.23-DNS-REBINDING-FIX.md
2025-12-12 17:30:22 +01:00
Chris Coutinho 4a79b37714 Merge pull request #389 from cbcoutinho/renovate/docker.io-library-nextcloud-32.x
chore(deps): update docker.io/library/nextcloud docker tag to v32.0.3
2025-12-12 12:23:44 +01:00
renovate-bot-cbcoutinho[bot] 76ae1c3603 chore(deps): update docker.io/library/nextcloud docker tag to v32.0.3 2025-12-12 11:09:06 +00:00
github-actions[bot] a60b88b80e bump: version 0.49.2 → 0.50.0 nextcloud-mcp-server-0.50.0 v0.50.0 2025-12-11 12:58:08 +00:00
Chris Coutinho e31b4433a1 Merge pull request #387 from cbcoutinho/feat/add-mcp-tool-annotations
feat: add MCP tool annotations for enhanced UX
2025-12-11 13:57:35 +01:00
Chris Coutinho 19183ad14a fix: address PR review feedback
Address all reviewer comments from PR #387:

1.  Add unit tests for annotations (tests/server/test_annotations.py)
   - 10 comprehensive test functions validating all annotation patterns
   - Tests for titles, read-only, destructive, idempotent operations
   - Validates specific ADR-017 decisions (webdav write, semantic search)
   - Cross-category consistency checks

2.  Fix nc_webdav_write_file idempotency classification
   - Changed from idempotentHint=False to idempotentHint=True
   - Rationale: Uses HTTP PUT without version control
   - Writing same content to same path = same end state (idempotent)

3.  Fix semantic search openWorldHint inconsistency
   - Changed from openWorldHint=False to openWorldHint=True
   - Rationale: Consistent with other Nextcloud tools
   - Nextcloud is external to MCP server (indexed data is implementation detail)

4.  Update ADR-017 with resolved decisions
   - Converted Open Questions to Resolved Questions
   - Added detailed rationale for webdav write and semantic search
   - Updated status from Proposed to Implemented
   - Added decision timeline with dates

5.  Add MCP Tool Annotations guidelines to CLAUDE.md
   - Comprehensive section with code examples for all patterns
   - Key principles documented (idempotency, destructive, open world)
   - References ADR-017 for detailed rationale

All OAuth tools verified to have proper annotations (oauth_tools.py lines 686-751).
2025-12-11 13:50:55 +01:00
Chris Coutinho e1412320a7 feat: add MCP tool annotations for enhanced UX
Add ToolAnnotations to all 105+ MCP tools across 13 modules to enable
better client-side UX with human-readable titles and behavioral hints.

Changes:
- Add title and ToolAnnotations to all @mcp.tool() decorators
- Apply correct idempotency classification per ADR-017
- Add destructiveHint for delete operations
- Set openWorldHint=False for semantic search (internal data only)

Modules updated:
- OAuth (4 tools): Authentication and provisioning
- Notes (7 tools): Note management
- WebDAV (11 tools): File operations
- Semantic (3 tools): Semantic search and RAG
- Calendar (16 tools): Events and todos
- Contacts (7 tools): Address book management
- Sharing (5 tools): File/folder sharing
- Tables (6 tools): Structured data
- Deck (25 tools): Kanban board management
- Cookbook (13 tools): Recipe management
- News (8 tools): RSS feed reader

Annotation patterns:
- Read operations: readOnlyHint=True, openWorldHint=True
- Create operations: idempotentHint=False, openWorldHint=True
- Update operations: idempotentHint=False, openWorldHint=True
- Delete operations: destructiveHint=True, idempotentHint=True, openWorldHint=True

See docs/ADR-017-mcp-tool-annotations.md for rationale and implementation details.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 12:45:02 +01:00
Chris Coutinho b9c94dfab0 Merge pull request #385 from cbcoutinho/renovate/docker.io-library-nginx-alpine
chore(deps): update docker.io/library/nginx:alpine docker digest to 289deca
2025-12-10 12:56:34 +01:00
Chris Coutinho 6f43c09bd0 Merge pull request #386 from cbcoutinho/renovate/ghcr.io-astral-sh-uv-0.x
chore(deps): update ghcr.io/astral-sh/uv docker tag to v0.9.17
2025-12-10 12:55:50 +01:00
Chris Coutinho 9e15e95c2b Merge pull request #384 from cbcoutinho/renovate/anthropics-claude-code-action-digest
chore(deps): update anthropics/claude-code-action digest to f0c8eb2
2025-12-10 12:54:21 +01:00
renovate-bot-cbcoutinho[bot] 1306c4cc9c chore(deps): update ghcr.io/astral-sh/uv docker tag to v0.9.17 2025-12-10 11:10:37 +00:00
renovate-bot-cbcoutinho[bot] f1247817d3 chore(deps): update docker.io/library/nginx:alpine docker digest to 289deca 2025-12-10 11:10:31 +00:00