MCP-Authentifizierung
Der MCP Server spricht OAuth 2.1 mit PKCE über einen HTTP-Transport (Streamable HTTP). Er ist stateless: keine In-Memory-Session-Map, keine Sticky Sessions, kein Per-Client-Transport-State. Der State liegt in Firestore, der Client trägt ein Bearer-JWT.
Workspace Gate
Nur Google-Identitäten aus der cloudpilots.com-Workspace dürfen sich
einloggen. Das Gate hängt am hd-Claim (Hosted Domain) des Google-ID-
Tokens und wird gegen MCP_ALLOWED_DOMAIN geprüft
(Default cloudpilots.com). Ein Email-Suffix-Check kommt bewusst nicht
zum Einsatz — Service-Account-Tokens haben keinen hd-Claim und werden
korrekt abgelehnt.
Token-Form
- Access Token: RS256 JWT, 15 Minuten TTL.
issundaudzeigen beide aufMCP_PUBLIC_URL. Public Keys liegen unter/.well-known/jwks.json(1 h Cache auf Verifier-Seite). - Refresh Token: opak, 30 Tage TTL mit einem 30-Sekunden-Rotation-
Grace-Window (das
expiresAtdes alten Tokens wird beim Rotate geschrumpft, nicht gelöscht — damit ein gleichzeitig fliegender Request nicht abschmiert). - Resource Indicator (RFC 8707): jeder
/authorize- und/token- Request mussresource=<MCP_PUBLIC_URL>mitschicken. Ein Trailing Slash wird toleriert.
Discovery-Endpoints
Alle direkt unter der Server-Root:
| Endpoint | Liefert |
|---|---|
/.well-known/oauth-authorization-server | RFC-8414-Metadata (authorization_endpoint, etc.) |
/.well-known/oauth-protected-resource | RFC-9728-Resource-Metadata |
/.well-known/jwks.json | Aktive Signing-Keys (RS256) |
Audit Log
Jeder Tool-Aufruf schreibt eine strukturierte JSON-Zeile nach stdout mit
channel: "mcp_audit". Drin stehen uid, clientId, Tool-Name, Start /
Ende, Dauer, Success / Failure und bei Erfolg die Pipeline-IDs.
Was nicht drin steht: User-Prompt-Inhalte — die wären PII, und ein
Routine-Log ist nicht der richtige Ort dafür.
Quoten
Per-uid Sliding-Window-Counter in Firestore:
| Limit | Default | Env Var |
|---|---|---|
| Stündliche Generations | 10 | MCP_HOURLY_QUOTA |
| Tägliche Generations | 60 | MCP_DAILY_QUOTA |
Quota-Errors kommen als 429-artige Tool-Errors zurück und sollten vom
Claude-Client dem User angezeigt werden, statt still im Hintergrund
nachzuziehen.