mirror of
https://github.com/jmagar/unraid-mcp.git
synced 2026-03-23 12:39:24 -07:00
docs: add Google OAuth setup guide and update README/CLAUDE.md
- Create docs/GOOGLE_OAUTH.md: complete OAuth setup walkthrough (Google Cloud Console, env vars, JWT key generation, troubleshooting) - README.md: add Google OAuth section with quick-setup steps + link - CLAUDE.md: add JWT key generation tip + link to full guide
This commit is contained in:
@@ -78,8 +78,15 @@ the MCP server requires Google login before any tool call.
|
||||
2. Authorized redirect URIs: `<UNRAID_MCP_BASE_URL>/auth/callback`
|
||||
3. Copy Client ID + Secret to `~/.unraid-mcp/.env`
|
||||
|
||||
**Generate a stable JWT signing key:**
|
||||
```bash
|
||||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
```
|
||||
|
||||
**Omit `GOOGLE_CLIENT_ID` to run without auth** (default — preserves existing behaviour).
|
||||
|
||||
**Full guide:** [`docs/GOOGLE_OAUTH.md`](docs/GOOGLE_OAUTH.md)
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
|
||||
31
README.md
31
README.md
@@ -14,7 +14,7 @@
|
||||
- 🔄 **Real-time Data**: WebSocket subscriptions for live metrics, logs, array state, and more
|
||||
- 📊 **Health Monitoring**: Comprehensive system diagnostics and status
|
||||
- 🐳 **Docker Ready**: Full containerization support with Docker Compose
|
||||
- 🔒 **Secure**: Proper SSL/TLS configuration and API key management
|
||||
- 🔒 **Secure**: Optional Google OAuth 2.0 authentication + SSL/TLS + API key management
|
||||
- 📝 **Rich Logging**: Structured logging with rotation and multiple levels
|
||||
|
||||
---
|
||||
@@ -25,6 +25,7 @@
|
||||
- [Quick Start](#-quick-start)
|
||||
- [Installation](#-installation)
|
||||
- [Configuration](#-configuration)
|
||||
- [Google OAuth](#-google-oauth-optional)
|
||||
- [Available Tools & Resources](#-available-tools--resources)
|
||||
- [Development](#-development)
|
||||
- [Architecture](#-architecture)
|
||||
@@ -229,7 +230,7 @@ UNRAID_VERIFY_SSL=true # true, false, or path to CA bundle
|
||||
|
||||
# Subscription Configuration
|
||||
UNRAID_AUTO_START_SUBSCRIPTIONS=true # Auto-start WebSocket subscriptions on startup (default: true)
|
||||
UNRAID_MAX_RECONNECT_ATTEMPTS=5 # Max WebSocket reconnection attempts (default: 5)
|
||||
UNRAID_MAX_RECONNECT_ATTEMPTS=10 # Max WebSocket reconnection attempts (default: 10)
|
||||
|
||||
# Optional: Log Stream Configuration
|
||||
# UNRAID_AUTOSTART_LOG_PATH=/var/log/syslog # Path for log streaming resource (unraid://logs/stream)
|
||||
@@ -245,6 +246,32 @@ UNRAID_MAX_RECONNECT_ATTEMPTS=5 # Max WebSocket reconnection attempts (def
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Google OAuth (Optional)
|
||||
|
||||
Protect the HTTP server with Google OAuth 2.0 — clients must complete a Google login before any tool call is executed.
|
||||
|
||||
Add these to `~/.unraid-mcp/.env`:
|
||||
|
||||
```bash
|
||||
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
|
||||
GOOGLE_CLIENT_SECRET=GOCSPX-your-secret
|
||||
UNRAID_MCP_BASE_URL=http://10.1.0.2:6970 # public URL of this server
|
||||
UNRAID_MCP_JWT_SIGNING_KEY=<64-char-hex> # prevents token invalidation on restart
|
||||
```
|
||||
|
||||
**Quick setup:**
|
||||
1. [Google Cloud Console](https://console.cloud.google.com/) → Credentials → OAuth 2.0 Client ID (Web application)
|
||||
2. Authorized redirect URI: `<UNRAID_MCP_BASE_URL>/auth/callback`
|
||||
3. Copy Client ID + Secret into `~/.unraid-mcp/.env`
|
||||
4. Generate a signing key: `python3 -c "import secrets; print(secrets.token_hex(32))"`
|
||||
5. Restart the server
|
||||
|
||||
Omit `GOOGLE_CLIENT_ID` to run without authentication (default behavior).
|
||||
|
||||
**Full guide:** [`docs/GOOGLE_OAUTH.md`](docs/GOOGLE_OAUTH.md)
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Available Tools & Resources
|
||||
|
||||
The single `unraid` tool uses `action` (domain) + `subaction` (operation) routing to expose all operations via one MCP tool, minimizing context window usage. Destructive actions require `confirm=True`.
|
||||
|
||||
165
docs/GOOGLE_OAUTH.md
Normal file
165
docs/GOOGLE_OAUTH.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Google OAuth Setup Guide
|
||||
|
||||
This document explains how to protect the Unraid MCP HTTP server with Google OAuth 2.0 authentication using FastMCP's built-in `GoogleProvider`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
By default the MCP server is **open** — any client on the network can call tools. Setting three environment variables enables Google OAuth 2.1 authentication: clients must complete a Google login flow before the server will execute any tool.
|
||||
|
||||
OAuth state (issued tokens, refresh tokens) is persisted to an encrypted file store at `~/.local/share/fastmcp/oauth-proxy/`, so sessions survive server restarts when `UNRAID_MCP_JWT_SIGNING_KEY` is set.
|
||||
|
||||
> **Transport requirement**: OAuth only works with HTTP transports (`streamable-http` or `sse`). It has no effect on `stdio` — the server logs a warning if you configure both.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Google account with access to [Google Cloud Console](https://console.cloud.google.com/)
|
||||
- MCP server reachable at a known URL from your browser (LAN IP, Tailscale IP, or public domain)
|
||||
- `UNRAID_MCP_TRANSPORT=streamable-http` (the default)
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create a Google OAuth Client
|
||||
|
||||
1. Open [Google Cloud Console](https://console.cloud.google.com/) → **APIs & Services** → **Credentials**
|
||||
2. Click **Create Credentials** → **OAuth 2.0 Client ID**
|
||||
3. Application type: **Web application**
|
||||
4. Name: anything (e.g. `Unraid MCP`)
|
||||
5. **Authorized redirect URIs** — add exactly:
|
||||
```
|
||||
http://<your-server-ip>:6970/auth/callback
|
||||
```
|
||||
Replace `<your-server-ip>` with the IP/hostname your browser uses to reach the MCP server (e.g. `10.1.0.2`, `100.x.x.x` for Tailscale, or a domain name).
|
||||
6. Click **Create** — copy the **Client ID** and **Client Secret**
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Configure Environment Variables
|
||||
|
||||
Add these to `~/.unraid-mcp/.env` (the canonical credential file for all runtimes):
|
||||
|
||||
```bash
|
||||
# Google OAuth (optional — enables authentication)
|
||||
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
|
||||
GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret
|
||||
|
||||
# Public base URL of this MCP server (must match the redirect URI above)
|
||||
UNRAID_MCP_BASE_URL=http://10.1.0.2:6970
|
||||
|
||||
# Stable JWT signing key — prevents token invalidation on server restart
|
||||
# Generate one: python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
UNRAID_MCP_JWT_SIGNING_KEY=your-64-char-hex-string
|
||||
```
|
||||
|
||||
**All four variables at once** (copy-paste template):
|
||||
|
||||
```bash
|
||||
cat >> ~/.unraid-mcp/.env <<'EOF'
|
||||
|
||||
# Google OAuth
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
UNRAID_MCP_BASE_URL=http://10.1.0.2:6970
|
||||
UNRAID_MCP_JWT_SIGNING_KEY=
|
||||
EOF
|
||||
```
|
||||
|
||||
Then fill in the blanks.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Generate a Stable JWT Signing Key
|
||||
|
||||
Without `UNRAID_MCP_JWT_SIGNING_KEY`, FastMCP derives a key on startup. Any server restart invalidates all existing tokens and forces every client to re-authenticate.
|
||||
|
||||
Generate a stable key once:
|
||||
|
||||
```bash
|
||||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
```
|
||||
|
||||
Paste the output into `UNRAID_MCP_JWT_SIGNING_KEY`. This value never needs to change unless you intentionally want to invalidate all sessions.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Restart the Server
|
||||
|
||||
```bash
|
||||
# Docker Compose
|
||||
docker compose restart unraid-mcp
|
||||
|
||||
# Direct / uv
|
||||
uv run unraid-mcp-server
|
||||
```
|
||||
|
||||
On startup you should see:
|
||||
|
||||
```
|
||||
INFO [SERVER] Google OAuth enabled — base_url=http://10.1.0.2:6970, redirect_uri=http://10.1.0.2:6970/auth/callback
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How Authentication Works
|
||||
|
||||
1. An MCP client connects to `http://<server>:6970/mcp`
|
||||
2. The server responds with a `401 Unauthorized` and an OAuth authorization URL
|
||||
3. The client opens the URL in a browser; the user logs in with Google
|
||||
4. Google redirects to `<UNRAID_MCP_BASE_URL>/auth/callback` with an authorization code
|
||||
5. FastMCP exchanges the code for tokens, issues a signed JWT, and returns it to the client
|
||||
6. The client includes the JWT in subsequent requests — the server validates it without hitting Google again
|
||||
7. Tokens persist to `~/.local/share/fastmcp/oauth-proxy/` — sessions survive server restarts
|
||||
|
||||
---
|
||||
|
||||
## Environment Variable Reference
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `GOOGLE_CLIENT_ID` | For OAuth | `""` | OAuth 2.0 Client ID from Google Cloud Console |
|
||||
| `GOOGLE_CLIENT_SECRET` | For OAuth | `""` | OAuth 2.0 Client Secret from Google Cloud Console |
|
||||
| `UNRAID_MCP_BASE_URL` | For OAuth | `""` | Public base URL of this server — must match the authorized redirect URI |
|
||||
| `UNRAID_MCP_JWT_SIGNING_KEY` | Recommended | auto-derived | Stable 32+ char secret for JWT signing — prevents token invalidation on restart |
|
||||
|
||||
OAuth is activated only when **all three** of `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, and `UNRAID_MCP_BASE_URL` are non-empty. Omit any one to run without authentication.
|
||||
|
||||
---
|
||||
|
||||
## Disabling OAuth
|
||||
|
||||
Remove (or empty) `GOOGLE_CLIENT_ID` from `~/.unraid-mcp/.env` and restart. The server reverts to unauthenticated mode and logs:
|
||||
|
||||
```
|
||||
WARNING [SERVER] No authentication configured — MCP server is open to all clients on the network.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**`redirect_uri_mismatch` from Google**
|
||||
The redirect URI in Google Cloud Console must exactly match `<UNRAID_MCP_BASE_URL>/auth/callback` — same scheme, host, port, and path. Trailing slashes matter.
|
||||
|
||||
**Tokens invalidated after restart**
|
||||
Set `UNRAID_MCP_JWT_SIGNING_KEY` to a stable secret (see Step 3). Without it, FastMCP generates a new key on every start.
|
||||
|
||||
**`stdio` transport warning**
|
||||
OAuth requires an HTTP transport. Set `UNRAID_MCP_TRANSPORT=streamable-http` (the default) or `sse`.
|
||||
|
||||
**Client cannot reach the callback URL**
|
||||
`UNRAID_MCP_BASE_URL` must be the address your browser uses to reach the server — not `localhost` or `0.0.0.0`. Use the LAN IP, Tailscale IP, or a domain name.
|
||||
|
||||
**OAuth configured but server not starting**
|
||||
Check `logs/unraid-mcp.log` or `docker compose logs unraid-mcp` for startup errors.
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
- OAuth protects the MCP HTTP interface — the Unraid GraphQL API itself still uses `UNRAID_API_KEY`
|
||||
- OAuth state files at `~/.local/share/fastmcp/oauth-proxy/` should be on a private filesystem; do not expose them
|
||||
- Restrict Google OAuth to specific accounts via the Google Cloud Console **OAuth consent screen** → **Test users** if you don't want to publish the app
|
||||
- `UNRAID_MCP_JWT_SIGNING_KEY` is a credential — store it in `~/.unraid-mcp/.env` (mode 600), never in source control
|
||||
Reference in New Issue
Block a user