Reviewer found two accuracy issues in the rewritten "Check Deployment Mode" section: - The AuthMode.OAUTH_SINGLE_AUDIENCE enum value is `oauth_single`, not `oauth_single_audience` (config_validators.py:28). A user grepping their container logs would have found nothing. - The "Configuring MCP server for <mode> mode" line was presented as a uniform <mode> substitution, but app.py:1170 hardcodes the literal string `OAuth mode` for OAuth, while app.py:1239 uses the enum value for the two BasicAuth modes. Split the boot-time block into per-mode subsections so each one shows the actual literal text users will see, and add a one-line note calling out the OAuth string difference. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 KiB
Running the Server
This guide covers different ways to start and run the Nextcloud MCP server.
Prerequisites
Before running the server:
- Install the server - See Installation Guide
- Configure environment - See Configuration Guide
- Set up authentication - See Authentication (multi-user deployments: see Login Flow v2)
Quick Start
Start the server using Docker:
# OAuth mode (--oauth, recommended for multi-user; required by Login Flow v2)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# BasicAuth mode (single-user or multi-user pass-through)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest
Note: Under
--oauththe MCP server is an OIDC relying party of a configurable IdP (Nextcloud's built-in OIDC by default; Keycloak, AWS Cognito, etc. viaOIDC_DISCOVERY_URL) and exposes an OAuth facade for MCP clients. Bearer tokens are validated against the IdP's JWKS. The MCP server does not forward client OAuth tokens to Nextcloud — Nextcloud is always reached via per-user app passwords (Login Flow v2) or Basic Auth credentials.
The server will start on http://127.0.0.1:8000 by default.
Running with Docker
Basic Docker Run
OAuth Mode (--oauth, recommended for multi-user)
The --oauth flag turns on the OAuth/OIDC layer. In this mode the MCP server is an OIDC relying party of a configurable IdP — Nextcloud's built-in OIDC by default, or any OIDC-compliant provider (Keycloak, AWS Cognito, Auth0, etc.) selected via OIDC_DISCOVERY_URL. The MCP server validates Bearer tokens against that IdP's JWKS and exposes an OAuth facade for MCP clients. Login Flow v2 is layered on top to acquire and store per-user Nextcloud app passwords for the data leg.
The MCP server registers itself with the IdP in one of two ways:
- Static client (preferred) — set
NEXTCLOUD_OIDC_CLIENT_IDandNEXTCLOUD_OIDC_CLIENT_SECRETin.env(matching a client you registered in your IdP — Nextcloud admin → OIDC, Keycloak realm → Clients, etc.). These env-var names predate multi-IdP support; they hold generic OIDC client credentials. - Dynamic Client Registration (fallback) — if the static creds aren't set and the IdP advertises a
registration_endpoint, the server self-registers via RFC 7591.
# OAuth with static (pre-registered) client — preferred
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
-e NEXTCLOUD_OIDC_CLIENT_ID=abc123 \
-e NEXTCLOUD_OIDC_CLIENT_SECRET=xyz789 \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# OAuth with auto-registration (DCR) — used when static creds are absent
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# OAuth on a custom port
docker run -p 127.0.0.1:8080:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# OAuth with specific apps only
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--enable-app notes --enable-app calendar
BasicAuth Mode
# BasicAuth (requires NEXTCLOUD_USERNAME/PASSWORD in .env)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest
# BasicAuth with specific apps
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest \
--enable-app notes --enable-app webdav
Docker with Persistent Token Storage
# Mount volume for persistent OAuth token storage
docker run -p 127.0.0.1:8000:8000 --env-file .env \
-v $(pwd)/data:/app/data \
--rm ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
Docker Compose
Create docker-compose.yml:
services:
mcp:
image: ghcr.io/cbcoutinho/nextcloud-mcp-server:latest
command: --oauth --enable-app notes --enable-app calendar
ports:
- "127.0.0.1:8000:8000"
env_file:
- .env
volumes:
- ./data:/app/data # Persistent token storage
restart: unless-stopped
Start the service:
# Start in foreground
docker-compose up
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop the service
docker-compose down
Server Options
Host and Port
# Bind to all interfaces (accessible from network)
docker run -p 0.0.0.0:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# Bind to localhost only (default, more secure)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# Use a different port (map host port 8080 to container port 8000)
docker run -p 127.0.0.1:8080:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
Security Note: Binding to 0.0.0.0 exposes the server to your network. Only use this if you understand the security implications.
Transport Protocols
The server supports multiple MCP transport protocols:
# Streamable HTTP (default, recommended)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--transport streamable-http
# SSE - Server-Sent Events (deprecated)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--transport sse
# HTTP
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--transport http
Warning
SSE transport is deprecated and will be removed in a future version of the MCP spec. Please migrate to
streamable-http.
Logging
# Set log level (critical, error, warning, info, debug, trace)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--log-level debug
# Production: use warning or error
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--log-level warning
Selective App Enablement
By default, all supported Nextcloud apps are enabled. You can enable specific apps only:
# Available apps: notes, tables, webdav, calendar, contacts, cookbook, deck
# Enable all apps (default)
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth
# Enable only Notes
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--enable-app notes
# Enable multiple apps
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--enable-app notes --enable-app calendar --enable-app contacts
# Enable only WebDAV for file operations
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--enable-app webdav
Use cases:
- Reduce memory usage and startup time
- Limit functionality for security/organizational reasons
- Test specific app integrations
- Run lightweight instances with only needed features
Development Mode
Running for Development
For active development with auto-reload, mount your source code as a volume:
# Development mode with source code mounted
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
-v $(pwd):/app \
-v $(pwd)/data:/app/data \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--log-level debug
For local development without Docker:
# Load environment variables
export $(grep -v '^#' .env | xargs)
# Run the server with auto-reload
uv run nextcloud-mcp-server run --oauth --log-level debug
CLI Subcommands
The nextcloud-mcp-server CLI has two main subcommands:
-
run- Start the MCP server (default command in Docker)uv run nextcloud-mcp-server run --oauth --host 0.0.0.0 --port 8000 -
db- Database migration management (Alembic)# Show current migration revision uv run nextcloud-mcp-server db current # Upgrade to latest migration uv run nextcloud-mcp-server db upgrade # Show migration history uv run nextcloud-mcp-server db history # Create new migration (developers only) uv run nextcloud-mcp-server db migrate "description of changes"
Database Migrations
Token storage uses Alembic for schema management:
- Automatic migrations: Database is upgraded automatically on server startup
- Backward compatibility: Pre-Alembic databases are automatically stamped with the initial revision
- Migration files: Located in
alembic/versions/ - For developers: When changing the schema:
- Create a migration:
uv run nextcloud-mcp-server db migrate "add new column" - Edit the generated file in
alembic/versions/to add SQL statements - Test upgrade:
uv run nextcloud-mcp-server db upgrade - Test downgrade:
uv run nextcloud-mcp-server db downgrade
- Create a migration:
See Database Migrations Guide for detailed information.
Connecting to the Server
Using MCP Inspector
MCP Inspector is a browser-based tool for testing MCP servers:
- Start your MCP server using Docker (see above)
- Start MCP Inspector:
npx @modelcontextprotocol/inspector - In the browser:
- Enter server URL:
http://localhost:8000 - Complete OAuth flow (if using OAuth)
- Explore tools and resources
- Enter server URL:
Using MCP Clients
MCP clients (like Claude Desktop, LLM IDEs) can connect to your server:
- Configure the client with your server URL
- Complete OAuth authentication (if enabled)
- Start interacting with Nextcloud through the LLM
Verifying Server Status
Check Server Health
The server exposes two Kubernetes-style probe endpoints:
# Liveness — server process is up (always 200 if running)
curl http://localhost:8000/health/live
# Readiness — server can reach Nextcloud and (if enabled) Qdrant
curl http://localhost:8000/health/ready
/health/live returns 200 OK as long as the process is running. /health/ready
returns 200 OK with a JSON body describing each dependency check, or 503 with
the same JSON body listing which checks failed — use the readiness probe when
troubleshooting connectivity to Nextcloud or Qdrant.
Check Deployment Mode
The server logs the detected deployment mode on startup. Look for these messages in the container logs:
At server boot (all modes):
INFO ✅ Configuration validated successfully for <mode> mode
INFO Health check endpoints enabled: /health/live, /health/ready
<mode> is one of single_user_basic, multi_user_basic, or
oauth_single, matching the MCP_DEPLOYMENT_MODE setting.
Additional BasicAuth-mode messages (at server boot):
INFO Configuring MCP server for <mode> mode
Here <mode> is the enum value (single_user_basic or multi_user_basic).
Additional OAuth-mode messages (at server boot):
INFO Configuring MCP server for OAuth mode
INFO OAuth client ready: <client-id>...
INFO OAuth configuration complete
Note the OAuth boot line logs the literal string OAuth mode, not the enum
value oauth_single.
Additional single-user BasicAuth messages (per MCP session):
These fire when the first MCP client connects, not at server boot — if you have just started the container and no client has connected yet, you will not see them in the logs:
INFO Starting MCP session in single-user BasicAuth mode
INFO Creating shared Nextcloud client with BasicAuth
INFO Client initialization complete
Process Management
Running as a Background Service
Use Docker Compose with restart: unless-stopped (see Docker Compose section above).
Monitoring Logs
# Docker (find container name first)
docker ps
docker logs -f <container-name>
# Docker Compose
docker-compose logs -f mcp
Performance Tuning
Production Settings
For production deployments, use Docker Compose with the recommended settings:
services:
mcp:
image: ghcr.io/cbcoutinho/nextcloud-mcp-server:latest
command: --oauth --log-level warning --transport streamable-http
ports:
- "127.0.0.1:8000:8000"
env_file:
- .env
volumes:
- ./data:/app/data
restart: unless-stopped
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
Scaling with Multiple Replicas
For higher load, use Docker Swarm or Kubernetes. See the Helm chart for Kubernetes deployments.
Troubleshooting
Server won't start
Check logs for errors:
# View container logs
docker logs <container-name>
# Or run with debug logging
docker run -p 127.0.0.1:8000:8000 --env-file .env --rm \
ghcr.io/cbcoutinho/nextcloud-mcp-server:latest --oauth \
--log-level debug
Common issues:
- Environment variables not loaded - Check your
.envfile - Port already in use - Use a different host port (e.g.,
-p 127.0.0.1:8080:8000) - OAuth configuration errors - See Troubleshooting
Can't connect to server
- Verify server is running:
curl http://localhost:8000/health/live - Check firewall settings
- Verify host binding (use
0.0.0.0to allow network access) - Check OAuth authentication if enabled
OAuth authentication fails
See Troubleshooting OAuth for detailed OAuth troubleshooting.
See Also
- Configuration Guide - Environment variables
- Authentication - Authentication modes
- Login Flow v2 - Recommended multi-user setup
- Troubleshooting - Common issues and solutions
- Installation - Installing the server