Files
nextcloud-mcp-server/docs/webhook-management-guide.md
T
Chris Coutinho 08d37a6597 docs: clean up astrolabe references after extraction
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>
2026-02-12 23:16:50 +01:00

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:

  1. Nextcloud 30+ with webhook_listeners app enabled
  2. Astrolabe app installed in Nextcloud (provides settings UI and credentials API)
  3. MCP server accessible from Nextcloud via HTTP(S)
  4. Vector sync enabled on the MCP server

Webhook Architecture Overview

The webhook system has two components:

  1. Webhook Registration - Configuring Nextcloud to send change notifications to the MCP server
  2. 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:

  1. 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)
    
  2. 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:

  1. 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
  2. App Password (for background sync):

    • Generated in Nextcloud Security settings
    • Stored encrypted in Nextcloud's oc_preferences via 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:

  1. Navigate to Nextcloud Settings → Astrolabe (Personal settings)
  2. Click "Authorize via OAuth" under "Option 1"
  3. Complete OAuth consent flow
  4. 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:

  1. Navigate to Nextcloud Settings → Security
  2. Generate a new app password (name it "Astrolabe" or "MCP Server")
  3. Return to Nextcloud Settings → Astrolabe
  4. Under "Option 2: App Password", paste the app password
  5. 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:

  1. Navigate to Nextcloud Settings → Astrolabe
  2. 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":

  1. Check if OAuth client is registered:
    SELECT id, name, client_identifier FROM oc_oidc_clients
    WHERE dcr = 1 ORDER BY id DESC LIMIT 5;
    
  2. Restart MCP server to trigger DCR re-registration
  3. Verify NEXTCLOUD_OIDC_CLIENT_ID and NEXTCLOUD_OIDC_CLIENT_SECRET are set

If background sync fails with "User no longer provisioned":

  1. Verify app password is stored:
    SELECT userid, configkey FROM oc_preferences
    WHERE appid = 'astrolabe' AND userid = 'username';
    
  2. 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:

  1. MCP client initiates OAuth flow
  2. User consents to requested scopes including offline_access
  3. MCP server stores refresh token for background operations

Alternatively, via Astrolabe UI:

  1. Navigate to Nextcloud Settings → Astrolabe
  2. Click "Authorize via OAuth"
  3. 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_access if 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:

  1. webhook_listeners app not enabled
  2. Webhook not registered for the event type
  3. Background job workers not running Fix:
php occ app:enable webhook_listeners
php occ background:cron  # or configure systemd cron