Chris Coutinho
8f45e996e8
feat: implement vector sync scanner and processor (ADR-007 Phase 2)
...
Implements background vector database synchronization using anyio
TaskGroups for BasicAuth mode with single-user credentials.
Scanner Implementation:
- Periodic document discovery (hourly, configurable)
- Timestamp-based change detection (Nextcloud vs Qdrant)
- Wake event for immediate scanning on-demand
- Supports both initial sync (all docs) and incremental sync (changes only)
- Detects deleted documents and queues for removal
Processor Implementation:
- Concurrent document processing pool (3 workers default)
- I/O-bound embedding generation via Ollama API
- Retry logic with exponential backoff (3 retries)
- Document chunking (512 words, 50-word overlap)
- Handles both index and delete operations
- Upserts vectors to Qdrant with rich metadata
App Lifespan Integration:
- Extended AppContext with background task state
- Modified app_lifespan_basic() to start tasks via anyio TaskGroups
- Graceful shutdown with coordinated task cancellation
- Only activates when VECTOR_SYNC_ENABLED=true
Embedding Service:
- OllamaEmbeddingProvider with TLS support
- Singleton pattern for shared client instances
- Batch embedding support for efficiency
- Auto-detects embedding dimension (768 for nomic-embed-text)
Qdrant Client:
- Async client wrapper with singleton pattern
- Auto-creates collection on first use
- COSINE distance metric for semantic similarity
- Integrates with embedding service for dimension detection
Health Check Enhancement:
- Added Qdrant status check to /health/ready endpoint
- Only checks when VECTOR_SYNC_ENABLED=true
- 2-second timeout for health probe
- Reports connection errors with details
Configuration:
- VECTOR_SYNC_ENABLED: Enable background sync
- VECTOR_SYNC_SCAN_INTERVAL: Scanner frequency (3600s default)
- VECTOR_SYNC_PROCESSOR_WORKERS: Concurrent processors (3 default)
- QDRANT_URL, QDRANT_API_KEY, QDRANT_COLLECTION: Vector DB config
- OLLAMA_BASE_URL, OLLAMA_EMBEDDING_MODEL: Embedding service config
Dependencies Added:
- qdrant-client>=1.7.0: Vector database client
Docker Compose:
- Added Qdrant service with health check
- Exposed ports 6333 (REST) and 6334 (gRPC)
- Configured MCP service with vector sync environment
- Added qdrant-data volume for persistence
Known Issue:
- FastMCP lifespan not triggering for streamable-http transport
- Background tasks will start once lifespan integration is complete
- Lifespan triggers on MCP session establishment, not server startup
Related: ADR-007 Background Vector Database Synchronization
🤖 Generated with Claude Code (https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-08 21:14:38 +01:00
github-actions[bot]
4ceaf45ffd
bump: version 0.26.0 → 0.26.1
2025-11-08 03:59:28 +00:00
Chris Coutinho
21b878a2e7
Merge pull request #265 from cbcoutinho/renovate/mcp-1.x
...
fix(deps): update dependency mcp to >=1.21,<1.22
2025-11-08 04:59:05 +01:00
github-actions[bot]
218f0bd366
bump: version 0.25.0 → 0.26.0
2025-11-08 03:48:50 +00:00
renovate-bot-cbcoutinho[bot]
c1e135c4a2
fix(deps): update dependency mcp to >=1.21,<1.22
2025-11-07 05:06:10 +00:00
github-actions[bot]
77e491beea
bump: version 0.24.1 → 0.25.0
2025-11-05 23:02:25 +00:00
Chris Coutinho
461971a1a8
Merge pull request #262 from cbcoutinho/feature/user-settings
...
Feature/user settings
2025-11-05 15:59:54 +01:00
Chris Coutinho
6cccd92b3b
build: Add type checking
2025-11-05 15:19:55 +01:00
github-actions[bot]
7052c19de0
bump: version 0.24.0 → 0.24.1
2025-11-04 12:28:13 +00:00
renovate-bot-cbcoutinho[bot]
3e988acb97
fix(deps): update dependency mcp to >=1.20,<1.21
2025-11-04 11:08:34 +00:00
github-actions[bot]
f587a4e31f
bump: version 0.23.0 → 0.24.0
2025-11-04 10:27:39 +00:00
Chris Coutinho
4e1d143e54
Merge remote-tracking branch 'origin/master' into feature/keycloak
2025-11-03 02:49:00 +01:00
github-actions[bot]
02a2c4a16f
bump: version 0.22.7 → 0.23.0
2025-11-03 01:48:39 +00:00
Chris Coutinho
babd60e08b
feat: Implement ADR-004 Hybrid Flow with comprehensive integration tests
...
Implement the ADR-004 Hybrid Flow OAuth pattern where the MCP server
intercepts the OAuth callback to obtain master refresh tokens while
maintaining PKCE security for clients.
## Implementation
### OAuth Routes (ADR-004 Hybrid Flow)
- Add `/oauth/authorize` endpoint: Intercepts client OAuth initiation
- Add `/oauth/callback` endpoint: Receives IdP callback, stores master token
- Add `/oauth/token` endpoint: Exchanges MCP code for client access token
- Implement PKCE code challenge/verifier validation
- Store OAuth sessions with state/challenge correlation
### MCP Server Integration
- Update `setup_oauth_config()` to return client_id and client_secret
- Initialize OAuth context in Starlette lifespan for login routes
- Add OAuth session storage to RefreshTokenStorage
- Configure authlib dependency for OAuth flow management
### Integration Tests
- Create `test_adr004_hybrid_flow.py` with Playwright automation
- Add `adr004_hybrid_flow_mcp_client` session-scoped fixture
- Test MCP session establishment with hybrid flow token
- Test tool execution using stored refresh tokens (on-behalf-of pattern)
- Test persistent access across multiple operations
- All tests passing: ✅ 3 passed in 8.82s
### Documentation
- Update ADR-004 with comprehensive Testing section
- Add integration test commands and coverage details
- Document test implementation and verification steps
- Create TESTING_INSTRUCTIONS.md for manual and automated testing
- Include manual test scripts for reference/debugging
## What This Enables
✅ PKCE code challenge/verifier flow
✅ MCP server intercepts OAuth callback and stores master refresh token
✅ Client receives MCP access token (not master token)
✅ MCP session establishment with hybrid flow token
✅ Tool execution using stored refresh tokens (on-behalf-of pattern)
✅ Multiple operations without re-authentication
✅ Proper token isolation (client never sees master token)
## Testing
Run ADR-004 integration tests:
```bash
uv run pytest tests/server/oauth/test_adr004_hybrid_flow.py --browser firefox -v
```
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-03 02:18:30 +01:00
Chris Coutinho
e331544cee
feat: Implement RFC 8693 token exchange for Keycloak (ADR-002 Tier 2)
...
Implements OAuth 2.0 Token Exchange (RFC 8693) enabling the MCP server to
exchange service account tokens for user-scoped tokens. This provides an
alternative to refresh tokens for background operations.
**Core Implementation:**
- Added `get_service_account_token()` method to KeycloakOAuthClient for
client_credentials grant
- Added `exchange_token_for_user()` method implementing RFC 8693 token exchange
- Fixed Fernet encryption key handling in RefreshTokenStorage (was incorrectly
base64 decoding already-encoded keys)
- Updated OAuth configuration to support offline_access scope and refresh token
storage infrastructure
**Keycloak Configuration:**
- Enabled `serviceAccountsEnabled` in realm-export.json
- Added `token.exchange.grant.enabled` attribute
- Added `client.token.exchange.standard.enabled` attribute (required for
Keycloak 26.2+ Standard Token Exchange V2)
- Fresh Keycloak imports now correctly enable token exchange
**Docker Compose:**
- Added TOKEN_ENCRYPTION_KEY and ENABLE_OFFLINE_ACCESS environment variables
- Created oauth-tokens volume for refresh token storage
- Configured both mcp-oauth and mcp-keycloak services
**Testing & Documentation:**
- Added tests/manual/test_token_exchange.py - Validates complete RFC 8693 flow
- Added tests/manual/test_nextcloud_impersonate.py - Documents session-based
impersonation limitations
- Added docs/oauth-impersonation-findings.md - Comprehensive investigation
findings and resolution documentation
**Verified Working:**
✅ Service account token acquisition (client_credentials grant)
✅ RFC 8693 token exchange for internal-to-internal tokens
✅ Exchanged tokens validate with Nextcloud APIs
✅ Keycloak 26.4.2 Standard Token Exchange V2 support
**Known Limitations:**
- User impersonation (requested_subject) requires Keycloak Legacy V1 with
preview features
- Cross-client token exchange limited to same realm
- Refresh token storage infrastructure ready but unused (MCP protocol limitation)
Dependencies: aiosqlite>=0.20.0
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:19 +01:00
github-actions[bot]
5259658458
bump: version 0.22.6 → 0.22.7
2025-10-29 11:18:41 +00:00
github-actions[bot]
e1aca04aff
bump: version 0.22.5 → 0.22.6
2025-10-29 10:57:44 +00:00
github-actions[bot]
e647c87dd8
bump: version 0.22.4 → 0.22.5
2025-10-29 10:54:54 +00:00
github-actions[bot]
202058bdc8
bump: version 0.22.3 → 0.22.4
2025-10-29 10:44:11 +00:00
github-actions[bot]
8221046d8a
bump: version 0.22.2 → 0.22.3
2025-10-29 10:35:58 +00:00
github-actions[bot]
9ec7637579
bump: version 0.22.1 → 0.22.2
2025-10-29 10:30:39 +00:00
github-actions[bot]
3878beaf65
bump: version 0.22.0 → 0.22.1
2025-10-29 10:17:08 +00:00
github-actions[bot]
0e7e74867f
bump: version 0.21.0 → 0.22.0
2025-10-29 09:32:27 +00:00
github-actions[bot]
57a2157c58
bump: version 0.20.0 → 0.21.0
2025-10-25 18:33:56 +00:00
yuisheaven
f0e5333e43
Merge branch 'master' into feature/introduce_files_parsing_with_unstructured_service_for_webdav_files_retrieval
2025-10-25 17:23:38 +02:00
github-actions[bot]
04e0ab127a
bump: version 0.19.1 → 0.20.0
2025-10-24 18:24:45 +00:00
Chris Coutinho
1117a83a52
Merge pull request #237 from cbcoutinho/feature/app-scopes
...
Feature/app scopes
2025-10-24 20:24:15 +02:00
github-actions[bot]
50a824155c
bump: version 0.19.0 → 0.19.1
2025-10-24 04:36:51 +00:00
renovate-bot-cbcoutinho[bot]
3baf10662f
fix(deps): update dependency mcp to >=1.19,<1.20
2025-10-24 04:06:55 +00:00
Chris Coutinho
d452684535
feat: Split read/write scopes into app:read/write scopes
2025-10-24 04:38:49 +02:00
github-actions[bot]
bfbaed9a66
bump: version 0.18.0 → 0.19.0
2025-10-23 23:50:51 +00:00
yuisheaven
29df645d53
Merge branch 'master' into feature/introduce_files_parsing_with_unstructured_service_for_webdav_files_retrieval
2025-10-23 21:30:09 +02:00
github-actions[bot]
87c6f077f3
bump: version 0.17.1 → 0.18.0
2025-10-23 10:23:48 +00:00
Chris Coutinho
c069d78f80
feat: Initialize JWT-scoped tools
2025-10-22 06:21:16 +02:00
yuisheaven
98627593d5
corrected smaller merge issues
2025-10-21 20:55:33 +02:00
yuisheaven
64649c902d
Merge branch 'master' into feature/introduce_files_parsing_with_unstructured_service_for_webdav_files_retrieval
2025-10-21 20:37:00 +02:00
github-actions[bot]
4984496d81
bump: version 0.17.0 → 0.17.1
2025-10-20 21:16:09 +00:00
Chris Coutinho
e8f1340133
fix(caldav): Fix caldav search() due to missing todos
2025-10-20 22:18:46 +02:00
Chris Coutinho
6ba87e7e05
chore: update caldav ref
2025-10-20 11:52:29 +02:00
github-actions[bot]
45bbf97033
bump: version 0.16.0 → 0.17.0
2025-10-19 22:55:23 +00:00
Chris Coutinho
a143123acc
fix(caldav): Check that calendar exists after creation to avoid race condition
...
Verify that field preservation tests still operate
2025-10-19 23:44:39 +02:00
Chris Coutinho
92e18825bc
feat(caldav): Add support for tasks
2025-10-19 18:02:43 +02:00
Chris Coutinho
d398a8c8e6
refactor: Migrate from internal CalendarClient to caldav library
2025-10-19 15:47:17 +02:00
github-actions[bot]
cb7a609ec2
bump: version 0.15.2 → 0.16.0
2025-10-19 00:13:49 +00:00
Chris Coutinho
5395f8d3d6
chore: Update lock file
2025-10-19 02:02:05 +02:00
Chris Coutinho
b72514bb32
ci: Add pytest-timeout to dev deps
2025-10-19 00:27:19 +02:00
Chris Coutinho
1459fe9bc8
test: Replace pytest-asyncio plugin fixtures with anyio fixtures
2025-10-18 22:02:25 +02:00
github-actions[bot]
a389f2940e
bump: version 0.15.1 → 0.15.2
2025-10-17 23:17:32 +00:00
github-actions[bot]
7549c988f4
bump: version 0.15.0 → 0.15.1
2025-10-17 02:49:37 +00:00
github-actions[bot]
0aeef1b87e
bump: version 0.14.3 → 0.15.0
2025-10-17 01:25:56 +00:00