Commit Graph

7 Commits

Author SHA1 Message Date
root 56d92c153b mail: robustes Decoding gegen unbekannte Charsets (x-unknown); OAuth-Token 30 Tage
- _safe_decode() faengt LookupError bei unbekannten/kaputten Mail-Charsets
  (z.B. 'x-unknown') ab, Fallback utf-8 -> latin-1. Verhindert Crash der
  Mail-Suche/Read bei einzelnen kaputt-kodierten Mails.
- common.py: OAuth access_token Lifetime 24h -> 30 Tage (weniger Re-Auth in claude.ai)
- .gitignore: *.before-* Backups ausschliessen

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 09:37:15 +02:00
Stefan Lohmaier 2618ecfc86 Add test client and automated integration test suite
- 'test' OAuth client maps to stefan's data via USER_ALIASES
- 38 tests covering OAuth (metadata, client_credentials, PKCE, invalid
  secret, no auth), Mail (accounts, folders, search), Calendar
  (calendars, tasks, events, search), Contacts (search, empty),
  Files (list, info), Notes (notebooks)
- Daily systemd timer (05:00) with NTFY notification on failure
- Shared token store (.active_tokens.json) for cross-process auth

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-12 10:33:01 +02:00
Stefan Lohmaier 80fc323374 Fix XML namespace handling for Radicale responses
Radicale uses default DAV: namespace (no d: prefix) and CR: for CardDAV
instead of c:. Fixed all regex patterns to handle both variants:
- <href> and <d:href>
- <displayname> and <d:displayname>
- <CR:address-data> and <c:address-data>
- <C:calendar-data> and <c:calendar-data>
- </response> and </d:response>

Also fixed calendar discovery to match <C:calendar/> resourcetype
instead of looking for VEVENT string in the response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-12 10:17:14 +02:00
Stefan Lohmaier 45cd6935fb Security: verify client_secret in authorization_code flow + shared token store
- Token exchange now requires valid client_secret (was missing)
- Access tokens stored in shared .active_tokens.json (cross-process)
- nginx rate limiting on /authorize and /token (10r/m, burst=5)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-12 09:34:18 +02:00
Stefan Lohmaier 30351f1bcf Switch to per-service subdomains, shared token store
URLs: mail.mcp.home.slohmaier.de, calendar.mcp..., etc.
No more path-prefix routing — each service has its own domain.
OAuth tokens stored in shared .active_tokens.json file so all
services can validate tokens issued by any service.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-12 09:13:54 +02:00
Stefan Lohmaier 7f0b03606a Add OAuth Authorization Code flow with PKCE for claude.ai
claude.ai uses the full OAuth Authorization Code flow, not client_credentials.
Flow: GET /authorize → auto-approve → redirect with code → POST /token
with code + code_verifier (PKCE S256).

Also fixes OAuth metadata URLs to use correct external scheme/host/prefix
via X-Forwarded-Proto, Host, and X-Forwarded-Prefix headers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-12 08:48:34 +02:00
Stefan Lohmaier fb642e47c8 Initial commit: 5 MCP servers for Mail, Calendar, Contacts, Files, Notes
Self-hosted MCP servers with OAuth client_credentials auth.
Each server connects to a different backend:
- Mail: reads Maildir IMAP backups
- Calendar/Tasks: CalDAV against Radicale
- Contacts: CardDAV against Radicale
- Files: WebDAV against oCIS
- Notes: Joplin REST API

Credentials externalized to config.json (not in repo).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-12 06:22:42 +02:00