docs: optimize CLAUDE.md for db scripts, uv run, and deployment modes

- Discourage raw docker exec for database queries; use scripts/dbquery.py
  and scripts/sqlitequery.py exclusively
- Ensure all python commands use uv run prefix (mcp run, pytest, etc.)
- Replace Progressive Consent section with concise Deployment Modes
  overview (single-user, multi-user BasicAuth, Login Flow v2)
- Normalize docker-compose to docker compose throughout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-04-01 15:52:51 +02:00
co-authored by Claude Opus 4.6
parent cbef665411
commit 270ef82527
+36 -75
View File
@@ -52,9 +52,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- **Decorators**: `@require_scopes`, `@require_provisioning` for access control - **Decorators**: `@require_scopes`, `@require_provisioning` for access control
- **Context pattern**: `await get_client(ctx)` to access authenticated NextcloudClient (async!) - **Context pattern**: `await get_client(ctx)` to access authenticated NextcloudClient (async!)
- **FastMCP decorators**: `@mcp.tool()`, `@mcp.resource()` - **FastMCP decorators**: `@mcp.tool()`, `@mcp.resource()`
- **Token acquisition**: `get_client()` handles both pass-through and token exchange modes - **Token acquisition**: `get_client()` resolves credentials per deployment mode (see Deployment Modes below)
- Pass-through (default): Simple, stateless (ENABLE_TOKEN_EXCHANGE=false)
- Token exchange (opt-in): RFC 8693 delegation (ENABLE_TOKEN_EXCHANGE=true)
### MCP Tool Annotations (ADR-017) ### MCP Tool Annotations (ADR-017)
@@ -199,20 +197,20 @@ uv run pytest tests/client/notes/test_notes_api.py -v
``` ```
**Important**: After code changes, rebuild the correct container: **Important**: After code changes, rebuild the correct container:
- Single-user tests: `docker-compose up --build -d mcp` - Single-user tests: `docker compose up --build -d mcp`
- OAuth tests: `docker-compose up --build -d mcp-oauth` - OAuth tests: `docker compose up --build -d mcp-oauth`
- Keycloak tests: `docker-compose up --build -d mcp-keycloak` - Keycloak tests: `docker compose up --build -d mcp-keycloak`
### Running the Server ### Running the Server
```bash ```bash
# Local development # Local development
export $(grep -v '^#' .env | xargs) export $(grep -v '^#' .env | xargs)
mcp run --transport sse nextcloud_mcp_server.app:mcp uv run mcp run --transport sse nextcloud_mcp_server.app:mcp
# Docker development (rebuilds after code changes) # Docker development (rebuilds after code changes)
docker-compose up --build -d mcp # Single-user (port 8000) docker compose up --build -d mcp # Single-user (port 8000)
docker-compose up --build -d mcp-oauth # Nextcloud OAuth (port 8001) docker compose up --build -d mcp-oauth # Nextcloud OAuth (port 8001)
docker-compose up --build -d mcp-keycloak # Keycloak OAuth (port 8002) docker compose up --build -d mcp-keycloak # Keycloak OAuth (port 8002)
``` ```
### Environment Setup ### Environment Setup
@@ -239,9 +237,11 @@ uv run python -m tests.load.benchmark --output results.json --verbose
**Credentials**: root/password, nextcloud/password, database: `nextcloud` **Credentials**: root/password, nextcloud/password, database: `nextcloud`
### Quick Query Script (Recommended for Agents) **Do NOT use `docker compose exec db mariadb` or `docker compose exec <service> sqlite3` directly.** Use the wrapper scripts below instead -- they handle credentials, output formatting, and avoid repeated docker exec approvals.
Use `scripts/dbquery.py` for single SQL statements without requiring approval for each `docker compose exec`: ### MariaDB (Nextcloud)
Use `scripts/dbquery.py` for all MariaDB queries:
```bash ```bash
# Basic query # Basic query
@@ -254,27 +254,6 @@ Use `scripts/dbquery.py` for single SQL statements without requiring approval fo
./scripts/dbquery.py -u nextcloud -p nextcloud "SHOW TABLES" ./scripts/dbquery.py -u nextcloud -p nextcloud "SHOW TABLES"
``` ```
### Direct Docker Access
For interactive sessions or complex operations:
```bash
# Connect to database
docker compose exec db mariadb -u root -ppassword nextcloud
# Check OAuth clients
docker compose exec db mariadb -u root -ppassword nextcloud -e \
"SELECT id, name, token_type FROM oc_oidc_clients ORDER BY id DESC LIMIT 10;"
# Check OAuth client scopes
docker compose exec db mariadb -u root -ppassword nextcloud -e \
"SELECT c.id, c.name, s.scope FROM oc_oidc_clients c LEFT JOIN oc_oidc_client_scopes s ON c.id = s.client_id WHERE c.name LIKE '%MCP%';"
# Check OAuth access tokens
docker compose exec db mariadb -u root -ppassword nextcloud -e \
"SELECT id, client_id, user_id, created_at FROM oc_oidc_access_tokens ORDER BY created_at DESC LIMIT 10;"
```
**Important Tables**: **Important Tables**:
- `oc_oidc_clients` - OAuth client registrations (DCR) - `oc_oidc_clients` - OAuth client registrations (DCR)
- `oc_oidc_client_scopes` - Client allowed scopes - `oc_oidc_client_scopes` - Client allowed scopes
@@ -283,9 +262,9 @@ docker compose exec db mariadb -u root -ppassword nextcloud -e \
- `oc_oidc_registration_tokens` - RFC 7592 registration tokens - `oc_oidc_registration_tokens` - RFC 7592 registration tokens
- `oc_oidc_redirect_uris` - Redirect URIs - `oc_oidc_redirect_uris` - Redirect URIs
### SQLite Databases (MCP Services) ### SQLite (MCP Services)
Use `scripts/sqlitequery.py` to query SQLite databases in MCP service containers: Use `scripts/sqlitequery.py` for all SQLite queries:
```bash ```bash
# List tables # List tables
@@ -338,48 +317,29 @@ Use `scripts/sqlitequery.py` to query SQLite databases in MCP service containers
3. MCP tools use context pattern: `get_client(ctx)` → `NextcloudClient` 3. MCP tools use context pattern: `get_client(ctx)` → `NextcloudClient`
4. All operations are async using httpx 4. All operations are async using httpx
### Progressive Consent Architecture (ADR-004) ### Deployment Modes
**Important**: Progressive consent is a *mechanism* for granting access, not a feature flag. The architecture is always present in OAuth mode. Whether provisioning tools are available is controlled by `ENABLE_OFFLINE_ACCESS`. The server supports three deployment modes, controlled by environment variables and docker compose profiles:
**What is Progressive Consent?** **1. Single-User** (profile: `single-user`)
- Dual OAuth flow architecture that separates client authentication (Flow 1) from resource provisioning (Flow 2) - Set `NEXTCLOUD_USERNAME` + `NEXTCLOUD_PASSWORD` (app password)
- Flow 1: MCP client authenticates directly to IdP with resource scopes (notes:*, calendar:*, etc.) - One shared Nextcloud identity for all MCP requests
- Token audience: "mcp-server" - Stateless, no persistent storage needed
- Client receives resource-scoped token for MCP session - Best for: personal instances, local development
- Flow 2: Server explicitly provisions Nextcloud access via separate login (only when `ENABLE_OFFLINE_ACCESS=true`)
- Server requests: openid, profile, email, offline_access
- Token audience: "nextcloud"
- Server receives refresh token for offline access
- Client never sees this token
- Provides clear separation between session tokens and offline access tokens
**Modes:** **2. Multi-User BasicAuth** (profile: `multi-user-basic`)
- **Pass-through mode** (`ENABLE_OFFLINE_ACCESS=false`, default): - Set `ENABLE_MULTI_USER_BASIC_AUTH=true`
- No Flow 2 provisioning - Each MCP client provides credentials via HTTP Authorization header
- Server uses client's token to access Nextcloud (pass-through) - Per-request client creation from extracted credentials
- No provisioning tools available - Best for: internal deployments where users manage their own Nextcloud credentials
- Suitable for stateless, client-driven operations
- **Offline access mode** (`ENABLE_OFFLINE_ACCESS=true`):
- Flow 2 provisioning available
- Server stores refresh tokens for background operations
- Provisioning tools available: `provision_nextcloud_access`, `check_logged_in`
- Suitable for background jobs and server-initiated operations
**When to use OAuth mode:** **3. Login Flow v2** (profile: `login-flow`)
- Multi-user deployments - Browser-based app password acquisition via Nextcloud's native Login Flow v2 API
- Background jobs requiring offline access (with `ENABLE_OFFLINE_ACCESS=true`) - Per-user app passwords stored encrypted in SQLite
- Enhanced security with separate authorization contexts - Application-level scope enforcement (defense-in-depth)
- Explicit user control over resource access - Works with any Nextcloud 16+ instance (no special apps required)
- Best for: production multi-user deployments, OAuth MCP integration
**When to use BasicAuth instead:** - See `docs/ADR-022-login-flow-v2.md` for architecture details
- Simple single-user deployments
- Local development and testing
**Key features:**
- No scope escalation - client gets exactly what it requests
- User explicitly authorizes via `provision_nextcloud_access` tool
- Clear security boundaries between MCP session and Nextcloud access
## MCP Response Patterns (CRITICAL) ## MCP Response Patterns (CRITICAL)
@@ -541,7 +501,7 @@ uv run pytest tests/server/oauth/test_oauth_core.py --browser firefox --headed -
**Setup**: **Setup**:
```bash ```bash
docker-compose up -d keycloak app mcp-keycloak docker compose up -d keycloak app mcp-keycloak
curl http://localhost:8888/realms/nextcloud-mcp/.well-known/openid-configuration curl http://localhost:8888/realms/nextcloud-mcp/.well-known/openid-configuration
docker compose exec app php occ user_oidc:provider keycloak docker compose exec app php occ user_oidc:provider keycloak
``` ```
@@ -557,7 +517,8 @@ docker compose exec app php occ user_oidc:provider keycloak
## Integration Testing with Docker ## Integration Testing with Docker
**Nextcloud**: `docker compose exec app php occ ...` for occ commands **Nextcloud**: `docker compose exec app php occ ...` for occ commands
**MariaDB**: `docker compose exec db mariadb -u [user] -p [password] [database]` for queries **MariaDB**: Use `./scripts/dbquery.py` for queries (see Database Inspection above)
**SQLite**: Use `./scripts/sqlitequery.py` for MCP service databases
### Querying Nextcloud Application Logs ### Querying Nextcloud Application Logs