Remove astrolabe-specific docs and sections that belong in the astrolabe repo. Update remaining references to point to the astrolabe repo where appropriate. - Fix .gitmodules SSH → HTTPS URL for astrolabe submodule - Remove bump-version.yml stale "astrolabe" scope comment - Delete blog-introducing-astrolabe.md (moved to astrolabe repo) - Remove "Astrolabe Background Token Refresh" section from auth-flows.md - Replace "Astrolabe User Setup" section in authentication.md with link - Remove "Astrolabe Internal URL" section from configuration.md - Remove "Webhook Presets (via Astrolabe UI)" from webhook guide Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 KiB
Webhook Management Guide
This guide explains how to enable and disable webhooks for vector sync in each MCP server deployment mode. Webhooks enable near-real-time synchronization of content changes to the vector database, complementing the default polling-based sync.
Related ADRs:
- ADR-010: Webhook-Based Vector Sync
- ADR-020: Deployment Modes and Configuration Validation
Prerequisites
Before enabling webhooks, ensure:
- Nextcloud 30+ with
webhook_listenersapp enabled - Astrolabe app installed in Nextcloud (provides settings UI and credentials API)
- MCP server accessible from Nextcloud via HTTP(S)
- Vector sync enabled on the MCP server
Webhook Architecture Overview
The webhook system has two components:
- Webhook Registration - Configuring Nextcloud to send change notifications to the MCP server
- Background Sync Credentials - Allowing the MCP server to access Nextcloud APIs on behalf of users
Both must be configured for webhooks to function properly.
Deployment Mode Specifics
1. Single-User BasicAuth
Configuration:
NEXTCLOUD_HOST=http://localhost:8080
NEXTCLOUD_USERNAME=admin
NEXTCLOUD_PASSWORD=password
VECTOR_SYNC_ENABLED=true
Enable Webhooks:
-
Register webhooks using occ commands (requires Nextcloud admin):
# Enable webhook_listeners app php occ app:enable webhook_listeners # Register webhooks for vector sync php occ webhook_listeners:add \ --event "OCP\Files\Events\Node\NodeCreatedEvent" \ --uri "http://mcp-server:8000/webhooks/nextcloud" \ --method POST # Repeat for other events (see Event Types below) -
Optionally reduce polling frequency:
VECTOR_SYNC_SCAN_INTERVAL=86400 # 24 hours
Disable Webhooks:
# List registered webhooks
php occ webhook_listeners:list
# Remove specific webhook by ID
php occ webhook_listeners:remove <webhook-id>
Notes:
- Simplest mode - admin credentials used for all operations
- No per-user provisioning required
- Background sync runs as the configured admin user
2. Multi-User BasicAuth Pass-Through
Configuration:
NEXTCLOUD_HOST=http://nextcloud.example.com
ENABLE_MULTI_USER_BASIC_AUTH=true
ENABLE_BACKGROUND_OPERATIONS=true
TOKEN_ENCRYPTION_KEY=<key>
TOKEN_STORAGE_DB=/app/data/tokens.db
VECTOR_SYNC_ENABLED=true
# OAuth client for Astrolabe API access
NEXTCLOUD_OIDC_CLIENT_ID=<client-id>
NEXTCLOUD_OIDC_CLIENT_SECRET=<client-secret>
Credential Architecture: This mode uses two separate credential mechanisms:
-
OAuth Session (for management API access, including webhooks):
- Obtained via browser OAuth flow (
/oauth/login) - Stores refresh token in MCP server's
tokens.db - Used for webhook registration/management APIs
- Obtained via browser OAuth flow (
-
App Password (for background sync):
- Generated in Nextcloud Security settings
- Stored encrypted in Nextcloud's
oc_preferencesvia Astrolabe - Used by background scanners to access Nextcloud APIs
Enable Webhooks:
Step 1: Complete OAuth Login (for Management API)
Users must authorize the MCP server to access their Nextcloud:
- Navigate to Nextcloud Settings → Astrolabe (Personal settings)
- Click "Authorize via OAuth" under "Option 1"
- Complete OAuth consent flow
- Verify the page shows "Background Sync Access: Active"
Step 2: Configure App Password (for Background Sync)
Since OAuth refresh tokens have short expiry, users should also configure an app password:
- Navigate to Nextcloud Settings → Security
- Generate a new app password (name it "Astrolabe" or "MCP Server")
- Return to Nextcloud Settings → Astrolabe
- Under "Option 2: App Password", paste the app password
- Click Save
Step 3: Register Webhooks (Admin)
Same as Single-User BasicAuth:
php occ webhook_listeners:add \
--event "OCP\Files\Events\Node\NodeCreatedEvent" \
--uri "http://mcp-server:8003/webhooks/nextcloud" \
--method POST
Disable Webhooks:
Per-User:
- Navigate to Nextcloud Settings → Astrolabe
- Click "Revoke Access" (for OAuth tokens) or "Revoke Access" (for app password)
System-Wide:
php occ webhook_listeners:remove <webhook-id>
Troubleshooting:
If OAuth login fails with "Access forbidden - Your client is not authorized":
- Check if OAuth client is registered:
SELECT id, name, client_identifier FROM oc_oidc_clients WHERE dcr = 1 ORDER BY id DESC LIMIT 5; - Restart MCP server to trigger DCR re-registration
- Verify
NEXTCLOUD_OIDC_CLIENT_IDandNEXTCLOUD_OIDC_CLIENT_SECRETare set
If background sync fails with "User no longer provisioned":
- Verify app password is stored:
SELECT userid, configkey FROM oc_preferences WHERE appid = 'astrolabe' AND userid = 'username'; - Ensure user completed both OAuth login AND app password setup
3. OAuth Single-Audience (Default OAuth Mode)
Configuration:
NEXTCLOUD_HOST=http://nextcloud.example.com
# No NEXTCLOUD_USERNAME/PASSWORD
ENABLE_BACKGROUND_OPERATIONS=true
TOKEN_ENCRYPTION_KEY=<key>
TOKEN_STORAGE_DB=/app/data/tokens.db
VECTOR_SYNC_ENABLED=true
Enable Webhooks:
Step 1: User Provisioning
Users authorize via OAuth with offline_access scope:
- MCP client initiates OAuth flow
- User consents to requested scopes including
offline_access - MCP server stores refresh token for background operations
Alternatively, via Astrolabe UI:
- Navigate to Nextcloud Settings → Astrolabe
- Click "Authorize via OAuth"
- Complete consent flow
Step 2: Register Webhooks (Admin)
php occ webhook_listeners:add \
--event "OCP\Files\Events\Node\NodeCreatedEvent" \
--uri "http://mcp-server:8001/webhooks/nextcloud" \
--method POST
Disable Webhooks:
Per-User:
- Via Astrolabe UI: Click "Disable Indexing" or "Disconnect"
- Via MCP tool: Use
revoke_nextcloud_accessif available
System-Wide:
php occ webhook_listeners:remove <webhook-id>
4. OAuth Token Exchange (RFC 8693)
Configuration:
NEXTCLOUD_HOST=http://nextcloud.example.com
ENABLE_TOKEN_EXCHANGE=true
ENABLE_BACKGROUND_OPERATIONS=true
TOKEN_ENCRYPTION_KEY=<key>
TOKEN_STORAGE_DB=/app/data/tokens.db
VECTOR_SYNC_ENABLED=true
Enable/Disable Webhooks: Same process as OAuth Single-Audience. The token exchange happens transparently when the MCP server accesses Nextcloud APIs.
5. Smithery Stateless
Configuration:
- Configuration from session URL params
VECTOR_SYNC_ENABLED=false(required)
Webhooks: Not supported. This mode is stateless with no persistent storage or background operations.
Webhook Event Types
Register these webhook events for full vector sync coverage:
File/Note Events
# Use BeforeNodeDeletedEvent for deletions (includes node.id)
php occ webhook_listeners:add --event "OCP\Files\Events\Node\NodeCreatedEvent" --uri "$MCP_URL/webhooks/nextcloud"
php occ webhook_listeners:add --event "OCP\Files\Events\Node\NodeWrittenEvent" --uri "$MCP_URL/webhooks/nextcloud"
php occ webhook_listeners:add --event "OCP\Files\Events\Node\BeforeNodeDeletedEvent" --uri "$MCP_URL/webhooks/nextcloud"
Calendar Events
php occ webhook_listeners:add --event "OCP\Calendar\Events\CalendarObjectCreatedEvent" --uri "$MCP_URL/webhooks/nextcloud"
php occ webhook_listeners:add --event "OCP\Calendar\Events\CalendarObjectUpdatedEvent" --uri "$MCP_URL/webhooks/nextcloud"
php occ webhook_listeners:add --event "OCP\Calendar\Events\CalendarObjectDeletedEvent" --uri "$MCP_URL/webhooks/nextcloud"
Tables Events
php occ webhook_listeners:add --event "OCA\Tables\Event\RowAddedEvent" --uri "$MCP_URL/webhooks/nextcloud"
php occ webhook_listeners:add --event "OCA\Tables\Event\RowUpdatedEvent" --uri "$MCP_URL/webhooks/nextcloud"
php occ webhook_listeners:add --event "OCA\Tables\Event\RowDeletedEvent" --uri "$MCP_URL/webhooks/nextcloud"
Security Considerations
Webhook Authentication
Configure WEBHOOK_SECRET to require authentication for incoming webhooks:
# MCP Server
WEBHOOK_SECRET=<generate-random-secret>
# Nextcloud webhook registration
php occ webhook_listeners:add \
--event "..." \
--uri "$MCP_URL/webhooks/nextcloud" \
--header "Authorization: Bearer <secret>"
Token Storage
- Refresh tokens and app passwords are encrypted using
TOKEN_ENCRYPTION_KEY - Store the key securely (environment variable, secrets manager)
- Different users have isolated credential storage
Monitoring
MCP Server Logs
# Docker
docker compose logs mcp-multi-user-basic | grep -i webhook
# Key log messages
# - "Queued document from webhook: ..." - Success
# - "Webhook authentication failed" - Auth error
# - "User X no longer provisioned" - Missing credentials
Nextcloud Logs
docker compose exec app cat /var/www/html/data/nextcloud.log | \
jq 'select(.message | contains("webhook"))' | tail
Database Checks
-- Check registered webhooks
SELECT * FROM oc_webhook_listeners;
-- Check OAuth clients
SELECT id, name, token_type FROM oc_oidc_clients WHERE dcr = 1;
-- Check user credentials stored by Astrolabe app
SELECT userid, configkey FROM oc_preferences WHERE appid = 'astrolabe';
Common Issues
"Access forbidden - Your client is not authorized to connect"
Cause: OAuth client registration expired or not present in Nextcloud Fix: Restart MCP server to trigger DCR re-registration
"User X no longer provisioned, stopping scanner"
Cause: Background sync credentials missing or expired Fix: User must complete credential provisioning (see mode-specific steps)
"Failed to fetch" in browser console during OAuth
Cause: Network issue between browser and MCP server callback endpoint
Fix: Verify MCP server is accessible at the configured NEXTCLOUD_MCP_SERVER_URL
Webhooks not firing
Causes:
webhook_listenersapp not enabled- Webhook not registered for the event type
- Background job workers not running Fix:
php occ app:enable webhook_listeners
php occ background:cron # or configure systemd cron