Skip to main content
Glama
GOOGLE_OAUTH_END_TO_END.md10.4 kB
# Google OAuth — End‑to‑End Guide for Claude History MCP This guide documents a complete, production‑ready Google OAuth setup for the Claude History MCP server running at `https://cc-history.tootie.tv`. It covers credentials, environment configuration, server wiring, reverse proxy, verification, headless login, client usage, troubleshooting, and security hardening. It reflects the implementation in this repository as of FastMCP 2.12.x. ## Overview - Server: Claude History MCP (`claude_history_mcp.server`), HTTP transport at `/mcp`. - Auth: FastMCP `GoogleProvider` (built on OAuth Proxy) mounts full OAuth endpoints on your server and proxies to Google (no DCR support needed upstream). - Reverse proxy: SWAG/Nginx terminates TLS and forwards both MCP and OAuth endpoints to the backend MCP server. - Clients: MCP clients (e.g., Claude, FastMCP Python Client) use `auth="oauth"` and auto‑negotiate the flow; tokens are cached locally for future sessions. ## Prerequisites - A Google Cloud project with OAuth 2.0 Client ID (Web application) - Authorized Redirect URI: `https://cc-history.tootie.tv/auth/callback` - Public HTTPS domain: `cc-history.tootie.tv` pointing at your reverse proxy - This repo deployed with Python 3.12+ and FastMCP 2.12.2+ ## Environment Configuration FastMCP reads server auth configuration from environment variables at startup. This project loads `.env` before constructing the server application, so these values must be present and correct. Required - `FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.google.GoogleProvider` - `FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID` — Google OAuth Client ID (…apps.googleusercontent.com) - `FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET` — Google OAuth Client Secret (starts with `GOCSPX-`) - `FASTMCP_SERVER_AUTH_GOOGLE_BASE_URL=https://cc-history.tootie.tv` - `FASTMCP_SERVER_AUTH_GOOGLE_REQUIRED_SCOPES=openid,https://www.googleapis.com/auth/userinfo.email` Recommended (hardening) - `FASTMCP_SERVER_AUTH_GOOGLE_ALLOWED_CLIENT_REDIRECT_URIS`: comma‑separated list of allowed client redirect patterns; e.g. `http://localhost:*,http://127.0.0.1:*` - This restricts which loopback URLs MCP clients can use. Notes - The `GoogleProvider` internally defaults `redirect_path` to `/auth/callback`. If you change it in Google Console, set `FASTMCP_SERVER_AUTH_GOOGLE_REDIRECT_PATH` to match. - Scopes can be extended (e.g., add `https://www.googleapis.com/auth/userinfo.profile`). ## Server Wiring (what this repo does) File: `claude_history_mcp/server.py` - Loads `.env` before importing/constructing FastMCP so env‑based auth is available immediately. - Constructs the app with an explicit Google provider if GOOGLE env is present to guarantee OAuth routes mount: ```python from fastmcp.server.auth.providers.google import GoogleProvider app = FastMCP("claude-history", auth=GoogleProvider(), mask_error_details=True) ``` - Adds two diagnostic tools protected by OAuth: - `whoami` — returns standard identity claims (iss, sub, email, name, picture) - `get_user_info` — simplified wrapper that returns `email`, `name`, `google_id`, `picture` ## Reverse Proxy (SWAG/Nginx) You must forward both the MCP path and the OAuth endpoints to the backend server (default backend: `http://100.122.19.93:8080`). Key locations to forward - `/mcp` — MCP endpoint (SSE/Streamable HTTP) - `/.well-known/oauth-authorization-server` — discovery - `/.well-known/openid-configuration` — discovery (OIDC shim) - `/register` — dynamic client registration - `/authorize` — authorization endpoint (redirects to Google) - `/token` — token exchange - `/auth/` — Google → server callback path (and any subpaths) - `/revoke` — optional token revocation - `/health` — health check Minimal SWAG snippet (server block only) ```nginx server { listen 443 ssl; listen [::]:443 ssl; server_name cc-history.tootie.tv; include /config/nginx/ssl.conf; # Upstream target set $upstream_app "100.122.19.93"; set $upstream_port "8080"; set $upstream_proto "http"; # MCP endpoint location /mcp { include /config/nginx/resolver.conf; proxy_http_version 1.1; proxy_buffering off; proxy_cache off; proxy_request_buffering off; proxy_set_header Connection ''; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass $upstream_proto://$upstream_app:$upstream_port; } # OAuth discovery location = /.well-known/oauth-authorization-server { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } location = /.well-known/openid-configuration { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } # OAuth endpoints location = /register { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } location = /authorize { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } location = /token { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } location = /revoke { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } location /auth/ { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } # Health location /health { proxy_pass $upstream_proto://$upstream_app:$upstream_port; } } ``` After editing - Validate and reload SWAG: - `docker exec -it swag nginx -t` - `docker exec -it swag s6-svc -h /var/run/s6/services/nginx` ## Running the Server Recommended (uses this repo’s startup/shutdown and HTTP transport): ```bash uv run python -m claude_history_mcp.server --host 0.0.0.0 --port 8080 ``` This initializes DB + TEI, loads `.env`, attaches Google OAuth, and serves at `/mcp`. ## Verification Check discovery endpoints - `curl -sS https://cc-history.tootie.tv/.well-known/oauth-authorization-server | jq .` - `curl -sS https://cc-history.tootie.tv/.well-known/openid-configuration | jq .` You should see JSON with keys like `authorization_endpoint`, `token_endpoint`, `registration_endpoint`, `issuer`, and scopes. Smoke test registration and authorize - `curl -i -X POST https://cc-history.tootie.tv/register -H 'Content-Type: application/json' -d '{}'` (expect JSON/validation error, not 404) - `curl -i 'https://cc-history.tootie.tv/authorize?client_id=x&redirect_uri=http://localhost:1234/cb&response_type=code&scope=openid&code_challenge=abc&code_challenge_method=S256&state=xyz'` (expect 3xx redirect) ## Client Usage Examples (this repo) - `examples/client_google_oauth.py` ```bash # Production python examples/client_google_oauth.py # Local (if running on localhost:8080) python examples/client_google_oauth.py --local # Call different tool (optional) python examples/client_google_oauth.py --tool whoami ``` Minimal snippet ```python from fastmcp import Client import asyncio async def main(): async with Client("https://cc-history.tootie.tv/mcp/", auth="oauth") as client: info = await client.call_tool("get_user_info") print(info) asyncio.run(main()) ``` ## Headless Login Options 1) SSH Port Forwarding (recommended) - Use a fixed callback port so you can forward it: ```python from fastmcp import Client from fastmcp.client.auth import OAuth oauth = OAuth("https://cc-history.tootie.tv/mcp/", callback_port=54321) async with Client("https://cc-history.tootie.tv/mcp/", auth=oauth) as client: print(await client.call_tool("get_user_info")) ``` - From your local machine: `ssh -L 54321:127.0.0.1:54321 user@HEADLESS_HOST` - Start the headless script; copy/open the authorization URL in your local browser. - Tokens are cached at `~/.fastmcp/oauth-mcp-client-cache` on the headless host. 2) Pre‑authenticate and copy cache - Authenticate once on a machine with a browser, then copy these files to the headless machine: - `~/.fastmcp/oauth-mcp-client-cache/https_cc-history_tootie_tv_client_info.json` - `~/.fastmcp/oauth-mcp-client-cache/https_cc-history_tootie_tv_tokens.json` ## Troubleshooting - `404 Not Found` on `/.well-known/...` or `/register` - Cause: OAuth routes not mounted or not forwarded by proxy. - Fixes: - Ensure `.env` is loaded before FastMCP construction (already handled in this repo). - Ensure app is constructed with `GoogleProvider()` so routes mount. - Add Nginx locations for discovery and OAuth endpoints (see above) and reload SWAG. - No browser opens / client fails before authorization - Headless: use fixed `callback_port` + SSH port forwarding (see Headless). - Cached invalid client: clear cache (`~/.fastmcp/oauth-mcp-client-cache/*_client_info.json` and `*_tokens.json`). - `invalid_client` or `redirect_uri_mismatch` - Ensure Google Console has exact Redirect URI: `https://cc-history.tootie.tv/auth/callback`. - If you customized `redirect_path`, ensure both Google and env match. - Stale credentials after server redeploy - The client may have cached a registration tied to prior server state. Clear client cache and retry; the provider will issue fresh registration. ## Security Hardening - Restrict client redirect URIs with `FASTMCP_SERVER_AUTH_GOOGLE_ALLOWED_CLIENT_REDIRECT_URIS` (e.g., `http://localhost:*,http://127.0.0.1:*`). - Use the minimum required scopes (currently `openid` and `userinfo.email`). - Keep TLS termination correct and forward `X-Forwarded-*` headers so the server advertises HTTPS URLs. - Rotate Google client secret periodically; store in secrets manager for production. - Keep FastMCP updated (2.12.x+); review CHANGELOG for auth updates. ## Useful Commands ```bash # Run server uv run python -m claude_history_mcp.server --host 0.0.0.0 --port 8080 # Check discovery curl -sS https://cc-history.tootie.tv/.well-known/oauth-authorization-server | jq . curl -sS https://cc-history.tootie.tv/.well-known/openid-configuration | jq . # Test client (prod) python examples/client_google_oauth.py # Clear FastMCP OAuth client cache (local machine) rm -f ~/.fastmcp/oauth-mcp-client-cache/*_{client_info,tokens}.json ``` ## References - [Project docs: GOOGLE_OAUTH.md](./GOOGLE_OAUTH.md) - [Project docs: OAUTH_PROXY.md](./OAUTH_PROXY.md) - [Project docs: AUTHENTICATION.md](./AUTHENTICATION.md) - [FastMCP docs](https://gofastmcp.com) (Authentication, OAuth Proxy, Google Provider) - [Google OAuth Console](https://console.cloud.google.com/apis/credentials)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmagar/docker-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server