feat: add API key bearer token authentication

- ApiKeyVerifier(TokenVerifier) — validates Authorization: Bearer <key>
  against UNRAID_MCP_API_KEY; guards against empty-key bypass
- _build_auth() replaces module-level _build_google_auth() call:
  returns MultiAuth(server=google, verifiers=[api_key]) when both set,
  GoogleProvider alone, ApiKeyVerifier alone, or None
- settings.py: add UNRAID_MCP_API_KEY + is_api_key_auth_configured()
  + api_key_auth_enabled in get_config_summary()
- run_server(): improved auth status logging for all three states
- tests/test_api_key_auth.py: 9 tests covering verifier + _build_auth
- .env.example: add UNRAID_MCP_API_KEY section
- docs/GOOGLE_OAUTH.md: add API Key section
- README.md / CLAUDE.md: rename section, document both auth methods
- Fix pre-existing: test_health.py patched cache_middleware/error_middleware
  now match renamed _cache_middleware/_error_middleware in server.py
This commit is contained in:
Jacob Magar
2026-03-16 11:11:38 -04:00
parent 6f7a58a0f9
commit cc24f1ec62
16 changed files with 406 additions and 69 deletions

View File

@@ -1,6 +1,6 @@
# Unraid API - Complete Reference Guide
> **⚠️ DEVELOPER REFERENCE ONLY** — This file documents the raw GraphQL API schema for development and maintenance purposes (adding new queries/mutations). Do NOT use these curl/GraphQL examples for MCP tool usage. Use `unraid(action=..., subaction=...)` calls instead. See `SKILL.md` for the correct calling convention.
> **⚠️ DEVELOPER REFERENCE ONLY** — This file documents the raw GraphQL API schema for development and maintenance purposes (adding new queries/mutations). Do NOT use these curl/GraphQL examples for MCP tool usage. Use `unraid(action=..., subaction=...)` calls instead. See [`SKILL.md`](../SKILL.md) for the correct calling convention.
**Tested on:** Unraid 7.2 x86_64
**Date:** 2026-01-21

View File

@@ -30,9 +30,8 @@ unraid(action="array", subaction="stop_array", confirm=True) # ⚠️ Stop
```python
unraid(action="disk", subaction="log_files") # List available logs
unraid(action="disk", subaction="logs", log_path="syslog", tail_lines=50) # Read syslog
unraid(action="disk", subaction="logs", log_path="/var/log/syslog") # Full path also works
unraid(action="live", subaction="log_tail", log_path="/var/log/syslog") # Live tail
unraid(action="disk", subaction="logs", log_path="/var/log/syslog", tail_lines=50) # Read syslog
unraid(action="live", subaction="log_tail", path="/var/log/syslog") # Live tail
```
### Docker Containers
@@ -64,7 +63,7 @@ unraid(action="notification", subaction="overview")
unraid(action="notification", subaction="list", list_type="UNREAD", limit=10)
unraid(action="notification", subaction="archive", notification_id="<id>")
unraid(action="notification", subaction="create", title="Test", subject="Subject",
description="Body", importance="normal")
description="Body", importance="INFO")
```
### API Keys

View File

@@ -26,15 +26,15 @@ This writes `UNRAID_API_URL` and `UNRAID_API_KEY` to `~/.unraid-mcp/.env`. Re-ru
unraid(action="health", subaction="test_connection")
```
2. Full diagnostic report:
1. Full diagnostic report:
```python
unraid(action="health", subaction="diagnose")
```
3. Check that `UNRAID_API_URL` in `~/.unraid-mcp/.env` points to the correct Unraid GraphQL endpoint.
1. Check that `UNRAID_API_URL` in `~/.unraid-mcp/.env` points to the correct Unraid GraphQL endpoint.
4. Verify the API key has the required roles. Get a new key: **Unraid UI → Settings → Management Access → API Keys → Create** (select "Viewer" role for read-only, or appropriate roles for mutations).
1. Verify the API key has the required roles. Get a new key: **Unraid UI → Settings → Management Access → API Keys → Create** (select "Viewer" role for read-only, or appropriate roles for mutations).
---